문제
가장 가까운 이웃 쿼리를하는 코드를 작업하고 있습니다. 검색에서 사용자가 데이터를 쿼리 할 수있는 방법의 두 가지 간단한 아이디어가 있습니다.
- 가장 가까운 N은 공간에서 주어진 지점을 가리 킵니다.
- 주어진 거리 내의 모든 지점.
내 코드에서 포인트는 포인트리스트에 넣고 포인트리스트는 컨테이너가 검색에서 발견 된 포인트를 추적하는 역할을합니다.
지금 당장 내 PointList 객체에는 하나의 생성자가 있습니다.
PointList( unsigned int maxvals ); // #1
내가 추가하고 싶은 다음 두 생성자는 다음과 같습니다.
PointList( float maxdist ); // #2
PointList( unsigned int maxvals, float maxdist ); // #3
내 질문은 : 사용자와 C ++ 컴파일러가 PointList에 대한 올바른 생성자를 생성하고 생성자 1과 2를 구분하는 방법은 무엇입니까? #3을 구현하고 MaxVals 및 MaxDist에 대한 임의의 큰 값을 정의하는 상수를 제공해야합니까? 또 다른 대안은 목록에 포인트를 추가하기위한 논리를 지배하는 다른 가벼운 물체 시스템을 작성하는 것일 수 있지만, 이는 간단한 아이디어에 대한 과잉처럼 느껴집니다.
나는 공식 교육의 혜택없이 때때로 C ++를 배운 과학자 인 사용자 에게이 투명성을 만들려고 노력하고 있습니다. 감사!
해결책
정수 유형에 대한 과부하 분해능은 두 가지 범주에서 발생하며, 이는 매우 대략 요약 할 수 있습니다.
- 프로모션 : 이것은보다 작은 유형의 변환입니다.
int
에게int
또는unsigned int
, 여부에 따라int
소스 유형의 모든 값을 저장할 수 있습니다. - 변환 : 이것은 모든 정수 유형에서 다른 정수 유형으로 변환됩니다.
유사하게, 부동 소수점 유형에 대한 변환은 두 가지 범주에서 발생합니다.
- 프로모션 : 이것은 전환입니다
float
에게double
- 변환 : 이것은 모든 부동 소수점 유형에서 다른 부동 소수점 유형으로 변환됩니다.
그리고 정수에서 떠 다니거나 뒤로 변환됩니다. 이것은 프로모션보다는 전환으로 순위가 매겨집니다. 프로모션은 전환보다 순위가 매겨지며 프로모션이 필요한 경우 해당 사례가 선호됩니다. 따라서 다음 생성자를 사용할 수 있습니다
PointList( int maxVals );
PointList( unsigned int maxVals );
PointList( long maxVals );
PointList( unsigned long maxVals );
PointList( double maxDist );
PointList( long double maxDist );
모든 정수 유형의 경우 첫 번째 생성자 그룹을 선택해야합니다. 그리고 모든 부동 소수점 유형의 경우 두 번째 생성자 그룹을 선택해야합니다. 원래 두 생성자가 쉽게 모호하게 만들 수 있습니다. float
그리고 unsigned int
, 당신이 통과하는 경우 int
, 예를 들어. 다른 두 인수 생성자의 경우 원하는 경우 솔루션을 사용할 수 있습니다.
즉, 파라미터의 의미를 결정하는 것은 매우 깨지기 쉬우므로 공장 기능도 사용할 것입니다. 대부분의 사람들은 다음과 같은 결과가 동일 할 것으로 예상합니다
PointList p(floor(1.5));
PointList u((int)1.5);
그러나 그것은 다른 상황을 초래할 것입니다.
다른 팁
생성자 대신 공장 방법을 사용하지 않는 이유는 무엇입니까? 공장 방법은 사용자 정의 가능한 이름의 장점이 있습니다.
static PointList createNearestValues(unsigned int maxvals) {}
static PointList createByDistance(float maxdist) {}
사용을 고려하십시오 진정한 typedefs. 클라이언트 코드의 일부에 대해서는 조금 더 노력하지만 정확성이 보장됩니다.
첫 번째 및 PointList (10F)는 PointList (10)를 호출합니다.
두 번째는 10.0을 사용할 수도 있습니다.
생성자 #1과 #2가있는 경우 삽입 값이 float 또는 int이고 변환이 없으면 올바른 생성자가 호출됩니다. 따라서 명시 적으로 호출하는 데 사용하는 숫자의 유형을 만들 수 있습니다 (예 : 1F 및 1). 생성자 #3은 실제로 필요하지 않기 때문에 많은 옵션이 아닌 것 같습니다. 사용할 수있는 숫자에 대한 기본값이 필요한 경우
PointList(int max, float max=VALUE)
그리고
PointList(float max, int max=VALUE)
다시 : 이것은 코드 가독성 측면에서 코드보다 더 많은 해를 끼치는 것 같습니다.
이것은 좋은 독서를 요구하고 있습니다 과부하 해상도.
나는 확실히 사용할 것입니다 명백한 생성자. 예에서 서명되지 않은 정수는 암시 적으로 변환되지 않습니다.
class A
{
public:
explicit A(float f){}
explicit A(int i){}
};
void test(){
unsigned int uinteger(0);
A a1(uinteger); //Fails, does not allow implicit conversions
A a2((float)uinteger); //OK, explicit conversion
float f(0.0);
A a3(f); //OK
int integer(0);
A a4(integer); //OK
}
오류 메시지는 이해하기에 쉽습니다.
: error C2668: 'A::A' : ambiguous call to overloaded function
: could be 'A::A(int)'
: or 'A::A(float)'