극좌표와 데카르트 좌표로 작업하는 프로그램을 작성 중입니다.
그것은 감각 점, 하나의 각 종류의 두 개의 서로 다른 구조체를 만들 수 있습니까 X
및 Y
회원들과 하나가 함께 R
하고 Theta
회원.
또는 너무 많이이며 함께 한 구조체를하는 것이 좋습니다 first
및 second
회원으로.
내가 쓰고있는 것은 간단하며 크게 바뀌지 않습니다. 그러나 디자인 관점에서 더 나은 점이 궁금합니다.
첫 번째 옵션이 더 낫다고 생각합니다. 더 읽기 쉽고 유형 검사의 이점을 얻습니다.
답변
두 솔루션을 모두 보았으므로 상황에 따라 다릅니다.
가독성을 위해 여러 구조체를 제안하는 것이 매우 효과적입니다. 그러나 일부 환경에서는 이러한 구조체에 대한 일반적인 조작을 원하며 행렬 * 벡터 연산과 같은 코드가 중복되는 것을 발견 할 수 있습니다. 아무도 벡터를 포팅하지 않았기 때문에 벡터의 풍미에서 특정 연산을 사용할 수 없을 때 실망 할 수 있습니다.
극단적 인 해결책 (우리가 결국에 준)은 get <0> () get <1> () 및 get <2> () 함수를 사용하여 CRTP 템플릿 기반 기본 클래스를 사용하여 요소를 일반적인 방식으로 얻는 것입니다. 그런 다음이 기본 클래스에서 파생 된 직교 또는 극좌표 구조에서 이러한 함수를 정의합니다. 모든 문제를 해결하지만 템플릿 메타 프로그래밍을 배워야하는 다소 어리석은 가격으로 제공됩니다. 그러나 템플릿 메타 프로그래밍이 이미 프로젝트에서 공정한 게임 인 경우 적합 할 수 있습니다.
답변
그렇습니다.
구조체의 가치는 단순한 이름으로 데이터를 캡슐화하는 것만이 아닙니다. 값은 의도를 체계화하여 컴파일러가 언젠가 위반하지 않는지 확인하는 데 도움을 줄 수 있다는 것입니다 (예 : 직교 좌표 세트에 대해 극좌표 좌표를 오해).
사람들은 그러한 끔찍한 세부 사항을 기억하는 데는 좋지 않지만 대담하고 독창적 인 계획을 세우는 데 능숙합니다. 컴퓨터는 세부 사항을 잘 이해하고 창의적 계획을 잘 못합니다. 따라서 컴퓨터에 대한 잔소리 세부 정보 유지 관리 작업을 컴퓨터로 전환하여 마음대로 계획을 세우는 것이 좋습니다.
답변
그렇습니다. 직교와 극좌표는 (그 자리에서) 현명하게 합리적인 좌표 표현 체계이지만, 절대적으로 절대로 혼합해서는 안됩니다 (점 직교가 {1,1} 인 경우 극좌표와 매우 다른 점입니다). }).
필요에 따라, 그것은 또한 같은 방법으로 인터페이스를 좌표 구현하는 가치가있을 수 있습니다 X()
, Y()
, Displacement()
및 Angle()
(또는 가능성 Radius()
과 Theta()
에 따라).
답변
결국, 프로그래밍의 목표는 유용한 작업을 수행하기 위해 트랜지스터 비트를 토글하는 것입니다. 그러나 그렇게 낮은 수준에서 생각하면 관리 할 수없는 열풍이 생겨 복잡성을 숨길 수있는 고급 프로그래밍 언어가 있습니다.
이름이 first
and second
인 멤버로 구조체를 하나만 만들면 이름이 의미가 없습니다. 본질적으로 메모리 주소로 취급합니다. 그것은 고급 프로그래밍 언어의 목적을 상실합니다.
또한, 그것들이 모두 표현 가능하기 때문에 double
그것들을 상호 교환하여 사용할 수 있는 것은 아닙니다. 예를 들어, θ 는 무 차원 각도이며, y 는 길이 단위입니다. 유형은 논리적으로 대체 할 수 없으므로 두 개의 호환되지 않는 구조체 여야합니다.
당신이 경우 정말 메모리 재사용 트릭을 재생해야 – 당신은 거의 확실하게 안 – 당신이 사용할 수있는 union
당신의 의도를 명확하게하기 위해 C의 유형입니다.
답변
첫째, @ Kilian-foth의 전적으로 건전한 대답에 따라 명시 적으로 두 가지를 모두 갖습니다.
그러나 다음을 추가하고 싶습니다.
질문 : 당신은 실제로 쌍으로 간주 될 때 두 가지에 일반적인 작업이 double
있습니까? 이것은 두 가지 모두에 적용되는 작업이 있다는 의미와 다릅니다. 예를 들어 ‘plot (Coord)’는가 Coord
극좌표인지 아니면 직교 좌표 인지를 관리합니다 . 반면에 파일을 유지하는 것은 데이터를 그대로 취급합니다. 실제로 일반 작업을 수행하는 경우 기본 클래스를 정의 std::pair<double, double>
하거나 tuple
언어에 있는 변환기를 정의 하십시오.
또한, 하나의 접근법은 하나의 좌표 유형을보다 근본적인 것으로 취급하고 다른 하나는 단지 사용자 또는 외부 상호 작용을 지원하는 것으로 취급 할 수있다.
따라서 모든 기본 조작이 코딩되었는지 확인한 Cartesian
다음로 변환 Polar
을 지원할 수 Cartesian
있습니다. 이렇게하면 여러 버전의 여러 작업을 구현하지 않아도됩니다.
답변
언어에 따라 가능한 방법은 두 클래스 모두 비슷한 메소드와 조작을 갖을 경우 클래스를 한 번 정의하고 유형 별명을 사용하여 유형의 이름을 다르게 지정하는 것입니다.
또한 클래스가 정확히 동일하면 하나만 유지할 수 있지만 클래스를 변경해야하는 즉시 유형이 이미 사용되었으므로이를 사용하여 코드를 수정할 필요가 없다는 장점이 있습니다. 분명히.
클래스의 사용법에 따라 (다형성이 필요한 경우 등) 또 다른 옵션은 두 가지 새 유형 모두에 대해 공용 상속을 사용하여 둘 다 나타내는 공통 유형과 동일한 공용 인터페이스를 사용하는 것입니다. 이것은 또한 유형의 개별 진화를 허용합니다.
답변
이 경우 코드의 오류가 발생하기 쉽기 때문에 동일한 멤버 이름을 갖는 것은 나쁜 생각이라고 생각합니다.
시나리오를 상상해보십시오. 두 개의 직교 점이 있습니다 : pntA와 pntB. 그런 다음 어떤 이유로 든 극좌표로 표시하는 것이 더 좋다고 결정하고 선언과 생성자를 변경하십시오.
이제 모든 작업이 다음과 같은 메소드 호출 인 경우 :
double distance = pntA.distanceFrom(pntB);
그럼 괜찮아 그러나 멤버를 명시 적으로 사용한 경우 어떻게해야합니까? 비교
double leftMargin = abs(pntA.x - pntB.x);
double leftMargin = abs(pntA.first - pntB.first);
첫 번째 경우 코드가 컴파일되지 않습니다. 오류가 즉시 표시되고 수정할 수 있습니다. 그러나 동일한 멤버 이름을 사용하는 경우 오류는 논리적 수준에서만 발생하므로 감지하기가 훨씬 어렵습니다.
객체 지향이 아닌 언어로 작성하면 잘못된 구조체를 함수에 전달하는 것이 더 쉽습니다. 다음 코드를 작성하지 못하게하는 이유는 무엇입니까?
double distance = calculate_distance_polar(cartesianPointA, polarPointB);
반면에 다른 데이터 유형을 사용하면 컴파일 중에 오류를 찾을 수 있습니다.