2009-04-02 4 views
15

알 수 없습니다. 3 시간 동안 코드 코드를 쳐다 보았는데 문제가 보이지 않습니다.Visual C++에서 "사용 가능한 적절한 기본 생성자가 없습니다."오류가 발생했습니다.

TwoDayPackage라는 클래스는 Package라는 클래스에서 파생됩니다.

내가 생성자를 정의하는 방법입니다

이 내가 생성자를 구현하는 방법이다
TwoDayPackage(string, string, string, string, int, string, string, string, string, int, float, float, float); 

: 이것은 내 주요 기능에서 사용하는 방법입니다

TwoDayPackage::TwoDayPackage(string sName, string sAddress, string sState, string sCountry, int sZIP, string rName, string rAddress, string rState, string rCountry, int rZIP, float weight, float cost, float flat) 
{ 
Package::Package(sName, sAddress, sState, sCountry, sZIP, rName, rAddress, rState, rCountry, rZIP, weight, cost); 
flatRate = flat; 
} 

.

TwoDayPackage pack2(senderName, senderAddress, senderState, senderCountry, senderZIP, receipientName, receipientAddress, receipientState, receipientCountry, receipientZIP, weight, cost, flat); 

내 주장 목록이 꽤 길다는 것을 알고 있습니다. 이유가 있습니다. 감사합니다. .

답변

23

사용해야 :

TwoDayPackage::TwoDayPackage(string sName, string sAddress, string sState, string sCountry, int sZIP, string rName, string rAddress, string rState, string rCountry, int rZIP, float weight, float cost, float flat) 
:Package(sName, sAddress, sState, sCountry, sZIP, rName, rAddress, rState, rCountry, rZIP, weight, cost) 
    { 
    flatRate = flat; 
    } 
+2

그러나 그것은 기본 ctor가 아닙니다. Dirk (그는 부드럽게 말했습니다.) –

+0

고마워, 이제 작동합니다. 누군가가 왜 작동하는지 설명 할 수 있습니까? 부모 클래스의 생성자를 호출하는 방법을 얻지 못합니다. 내가 뭘했는지 (부모 생성자를 호출하면 작동 할 것입니다) 감사합니다. – chustar

+1

기본 구문은 이니셜 라이저 목록에서 호출해야합니다. 지정하지 않으면 컴파일러에서 기본 클래스의 기본 생성자를 호출하여 문제를 호출하려고한다고 생각합니다. – dirkgently

4

대답은 dirkgently의입니다. 설명은 C++의 초기화 순서입니다.

클래스를 생성 할 때 모든 기본 클래스가 먼저 생성됩니다. 초기화 목록의 생성자에 대한 호출을 제공하면 적절한 생성자가 호출됩니다. 기본 클래스가 초기화 목록에 나타나지 않으면 기본 구성이 생성됩니다. 이 모든 것은 전에이 생성자 블록 (중괄호)에 들어가기 전에 발생합니다.

22

기본 ctor는 인수없이 호출 할 수 있습니다. 기본의 ctor 중 서명

ClassName::ClassName(); 

또는 모든 인수가 기본이 있어야이 있습니다이 코드 적어도 하나가 없습니다.

그렇다면 구문에 대한 더크의 주장은 정확합니다. 부모 클래스 ctor를 호출하려면 해당 콜론 뒤에 사용해야합니다.


@ dirkgently의 답변은 올바른 구문을 보여 주지만 약간 확장 해 보겠습니다. 당신은 두 개의 클래스

public class Package { 
    // ... 
    Package(/* that horrible ctor arg list */){/*...*/} 
    // ... 
} 

public class TwoDayPackage : public Package { 
    // ... 
    TwoDayPackage(/* another horrible ctor */); // declaration only 
    // ... 
} 

있어 그리고 당신은 그것을

TwoDayPackage::TwoDayPackage(string sName, string sAddress, 
          string sState, string sCountry, 
          int sZIP, string rName, 
          string rAddress, string rState, 
          string rCountry, int rZIP, 
          float weight, float cost, float flat) 
{ 

    Package::Package(sName, sAddress, sState, sCountry, sZIP, 
         rName, rAddress, rState, rCountry, rZIP, 
         weight, cost); 
    flatRate = flat; 
} 

을 정의하기 위해 함께 온 ... 그러나 그것은 작동하지 않는 이유는 무엇입니까? 왜? 기본적으로, C++에게 말하는 것은 의미가 없기 때문에 : Package::Package은 수퍼 클래스의 ctor의 이름을 지정하는 것으로 그 일을 수행하지 않습니다. 당신은 새로운 연산자를 사용하여

 Package foo = new 
     Package::Package(sName, sAddress, sState, sCountry, sZIP, 
          rName, rAddress, rState, rCountry, rZIP, 
          weight, cost); 

을 클래스 패키지의 새로운 객체를 생성 할 수 있습니다하지만 당신이 원하는 무엇을 아직 아니다; 무엇 원하는 그 arg 목록을 사용하여 TwoDayPackage의 패키지 부분을 C + +를 지시하는 것입니다. 컴파일러는 이미 부모 클래스가 무엇인지 알고 있기 때문에 완전한 이름을 가질 필요는 없습니다.

또한 자식 Ctr에 값을 할당 할 수도 있지만 컴파일러에서 "여러 번 우물로 이동"코드를 생성 할 때 비효율적입니다. 따라서 C++은 Dirk가 보여 주듯이 콜론 다음에 이니셜 라이저를 넣는 특수 구문을 사용합니다.

한가지 더 : 당신은 그냥 어쨌든 평면에 매개 변수를 할당하고 있기 때문에, 당신은 더 많은위한 C++ FAQ 라이트의

TwoDayPackage::TwoDayPackage(string sName, string sAddress, 
          string sState, string sCountry, 
          int sZIP, string rName, 
          string rAddress, string rState, 
          string rCountry, int rZIP, 
          float weight, float cost, float flat) : 
    Package(sName, sAddress, sState, sCountry, sZIP, 
      rName, rAddress, rState, rCountry, rZIP, weight, cost), 
    flatRate(flat) 
{ 
} 

확인 this section을 말할 수있다.