8

私が3つのクラスを持っているとしましょう- 、、、のサブクラスAnimalです(これは最初の講義のように聞こえますが、私が約束する宿題ではなく、実際のコードを単純化するだけです)CatDogCatDogAnimal

Dog* spike = new Dog(); 
Cat* puss = new Cat();   

int main(int argc, char** argv)
{
    function(spike, puss);
    return 0;
}

void function(Animal *pet, Animal *pet2)
{
   magic->andSoForth();
}

これで、次のエラーが生成されます。

Cannot convert parameter 1 from 'Dog *' to 'Animal'
  No constructor could take the source type,
    or constructor overload resolution was ambiguous

パラメータを完全に一致するように変更すると、同様のエラーが生成されますが、クラスから同じクラスに変換できないというだけです。

スーパークラスから継承するサブクラス関数とメンバーを正常に呼び出したので、これは論理的には機能するはずです。この言語が私に論理を曲げさせたいのは、どのようにねじれたのかわかりません。

編集

解決策はたまたま次のとおりです。ポインタはすべての人を混乱させます。

  • ポインタを宣言します。
  • ポインターを処理しない関数への引数としてポインターを送信します。

私の例では、ポインターが必要な関数に「not-pointers」を送信しました。これを切り替えただけです。今では正常に動作します。

4

5 に答える 5

7

新しいオブジェクトを動的に割り当てると、そのオブジェクトへのポインタを取得します。したがって、次のようにポインタに格納する必要があります。

Dog* spike = new Dog();
Cat* puss = new Cat();

spike次に、またはpussを型の任意のパラメータに渡すことができます。ただし、実際にから継承するとAnimal*仮定Dogします。これがC++のポリモーフィズムの基本です。CatAnimal

クラスタイプである「 pointertocv 」タイプのprvalueは、の基本クラス(Clause 10)であるタイプ「 pointertocv 」のprvalueに変換できます。DD BBD

もちろん、次のようにすぐに保存することもできますAnimal*

Animal* spike = new Dog();
Animal* puss = new Cat();

それらを忘れないでくださいdelete。さらに良いことに、まったく使用newしないでください。

Dog spike;
Cat puss;
void function(const Animal&, const Animal&);
function(spike, puss);
于 2012-12-02T19:47:08.127 に答える
5

あなたが抱えている問題は、ポインタを非ポインタに割り当てること、またはその逆であると考えるのが妥当です。しかし、あなたのコードは実際のコードではなく、あなたのエラーメッセージは明らかに実際のエラーメッセージではありません。したがって、それはすべて当て推量であり、特に「これはそれです」と言うすでに投稿された回答です(おそらくそうですが、必ずしもそうとは限りません。不確実性は完全にあなた自身の責任です)。


編集:私がこれを投稿してから10秒後にOPが質問のコードを変更しました。

コードはまだ、意図されたエラーメッセージと一致しません。

この質問は変わるので、私はこの質問を追いかけるつもりはありません。


さて、何をすべきかについて…


使用しないでくださいnew

経験豊富なC++プログラマーnewは、適切なコードにラップされて、制御された方法で使用することがあります。能力のないC++プログラマーnewは、当然のことながらよく使用します。しかし、一般的には必要ありませんし、問題があるので、デフォルトでは使用しない方がよいでしょう。

次に、(表示を怠った)プログラムは次のようになります。

#include <iostream>

struct Animal {};
struct Dog: Animal {};
struct Cat: Animal {};

void function(Animal const& pet1, Animal const& pet2 )
{
   //magicAndSoForth();
}

int main()
{
    Dog spike; 
    Cat puss;

    function( spike, puss );
}
于 2012-12-02T20:21:16.917 に答える
1

あなたのプロトタイプはfunctionほぼ間違いなく言う

void function(Animal pet1, Animal pet2);

またはそれに非常に似たもの。function(後に表示されるので、プロトタイプがあることはわかっています。前方宣言しなかった場合、C ++は、間違ったタイプの引数を使用しているのではなく、まったくmain見つからなかったと文句を言います。)function

問題は、あなたの本当のfunctionポインタを取ることです。そしてmain、本物の前に現れるのでfunction、それは見えません。実際のsを取る宣言のみが表示されるAnimalため、それを使用しようとしますが、AnimalポインターはAnimalではないため、失敗します。(C ++では、オーバーロードの可能性があるため、プロトタイプとの実際のfunction違いは問題ありません。コンパイラーが知る限りfunction(Animal, Animal)、別の変換ユニットに存在し、定義しているだけですfunction(Animal*, Animal*)。)

の宣言についてコードを調べてfunction

void function(Animal *pet1, Animal *pet2);

実際の関数のシグネチャと一致させます。

PS:関連するすべての宣言を含めていれば、これは非常に簡単に理解できたでしょう。

PPS:Alfが提案しているように、代わりに参照を取得することをお勧めします。しかし、とにかくそれを行うには、最初にプロトタイプの不一致を修正する(または実際の関数をそれを使用するコードの前に表示させる)必要があります

于 2012-12-02T22:25:53.333 に答える
-1

さて、あなたがする必要があるのはこれです

Animal *spike = new Dog();
Animal *puss = new Cat();

基本的に、すべてのポインター定義は基本クラスのものである必要があり、これらは派生クラスポインターで初期化できます。

于 2012-12-02T19:45:48.970 に答える
-4

これはそれがどのように見えるべきかです。

Dog* spike = new Dog();
Cat* puss = new Cat();

function(*spike, *puss);

void function(Animal pet, Animal pet2)
{
   //magic
}

テストされ、動作しています。

于 2012-12-02T20:57:24.380 に答える