型が一致しない?

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
adu

型が一致しない?

#1

投稿記事 by adu » 7年前

それぞれ4つのインスタンスからなる2つのリストの両方から1つずつインスタンスを選び,考えられる全ての組みあわせ(16通り)でfunc関数を実行し,trueになるものを探したいと思い,次のように書きました.
Sub1 対 Sub1 , Sub1 対 Sub2 , Sub1 対 Sub2 , Sub2 対 Sub1 の4通りの インスタンス 対 引数 の組みあわせが考えられます.
そのうち後の2つは bool Sub1::func(const &Sub2) と bool Sub2::func(const &Sub1) の内部を同じ処理にすることで対応する予定です.

で,p->func(*q); //ここ の部分でエラーが発生し,赤い破線が引かれます.

Error: オーバーロードされた関数"Super::func"のインスタンスが引数リストと一致しません
  引数の型: (Super)
  オブジェクトの型は Super です

SuperとSuperで一致しているのに,何故このようなエラーが出発生するのでしょうか?
また,複数の組みあわせに対応する処理も面倒に見えますし,全体的に多様態を利用した(?)もっとうまい方法がある気がするのですが...

本当はSTGの長方形と円の当たり判定クラスなのですが,長いのでこのような名前にしました.

コード:

 
#include <iostream>
using namespace std;

class Super;
class Sub1;
class Sub2;

class Super{
public:
	Super(){ next = 0; }
	Super* next;
	virtual bool func(const Sub1& sub1){
		cout << "virtual bool func(const Sub1& sub1)" << endl;
		return true;
	}
	virtual bool func(const Sub2& sub2){
		cout << "virtual bool func(const Sub2& sub2)" << endl;
		return true;
	}
};

class Sub1 : public Super{
public:
	Sub1(){ next = 0; }

	bool func(const Sub1& sub1){
		cout << "bool Sub1::hit(const Sub1&)" << endl;
		return true;
	}

	bool func(const Sub2& sub2){
		cout << "bool Sub1::hit(const Sub2&)" << endl;
		return true;
	}
};

class Sub2 : public Super{
public:
	Sub2(){ next = 0; }

	bool func(const Sub1& sub1){
		cout << "bool Sub2::hit(const Sub1&)" << endl;
		return true;
	}

	bool func(const Sub2& sub2){
		cout << "bool Sub2::hit(const Sub2&)" << endl;
		return true;
	}
};

int main(void){
	Super super = Super();

	Sub1 sub11 = Sub1();
	Sub1 sub12 = Sub1();
	Sub2 sub21 = Sub2();
	Sub2 sub22 = Sub2();

	sub11.next = &sub12;
	sub12.next = &sub21;
	sub21.next = &sub22;
	sub22.next = 0;

	Sub1 sub13 = Sub1();
	Sub1 sub14 = Sub1();
	Sub2 sub23 = Sub2();
	Sub2 sub24 = Sub2();

	sub13.next = &sub14;
	sub14.next = &sub23;
	sub23.next = &sub24;
	sub24.next = 0;

	bool rtn=false;
	for(Super *p = &sub11; p->next != 0; p = p->next){
		for(Super *q = &sub13; q->next!=0; q = q->next){
			if( p->func(*q) ){
				rtn = true;
				goto out;
		}
out:
	}

	int i; std::cin >> i;
	return 0;
}

salsaww

Re: 型が一致しない?

#2

投稿記事 by salsaww » 7年前

まず、出来ない理由は単純に引数で実際に使われてる型がSuper型なので、
キャストするなりの必要があります。
で、キャストするにも、自前の型なので、ちゃんと必要な変換用コンストラクタを作る必要があります。

※Sub1と同じようにSub2にも変換用コンストラクタが必要でしょう。

コード:

 
#include <iostream>
using namespace std;
 
class Super;
class Sub1;
class Sub2;
 
class Super{
public:
    Super(){ next = 0; }
    Super* next;
    virtual bool func(Sub1&  const sub1){
        cout << "virtual bool func(const Sub1& sub1)" << endl;
        return true;
    }
    virtual bool func(Sub2& const sub2){
        cout << "virtual bool func(const Sub2& sub2)" << endl;
        return true;
    }
};
 
class Sub1 : public Super{
public:
	Sub1(Super x){
		next =x.next;
	}
    Sub1(){ next = 0; }
 
    bool func(const Sub1& sub1){
        cout << "bool Sub1::hit(const Sub1&)" << endl;
        return true;
    }
 
    bool func(const Sub2& sub2){
        cout << "bool Sub1::hit(const Sub2&)" << endl;
        return true;
    }
};
 
class Sub2 : public Super{
public:
    Sub2(){ next = 0; }
 
    bool func(const Sub1& sub1){
        cout << "bool Sub2::hit(const Sub1&)" << endl;
        return true;
    }
 
    bool func(const Sub2& sub2){
        cout << "bool Sub2::hit(const Sub2&)" << endl;
        return true;
    }
};
 
int main(void){
    Super super = Super();
 
    Sub1 sub11 = Sub1();
    Sub1 sub12 = Sub1();
    Sub2 sub21 = Sub2();
    Sub2 sub22 = Sub2();
 
    sub11.next = &sub12;
    sub12.next = &sub21;
    sub21.next = &sub22;
    sub22.next = 0;
 
    Sub1 sub13 = Sub1();
    Sub1 sub14 = Sub1();
    Sub2 sub23 = Sub2();
    Sub2 sub24 = Sub2();
 
    sub13.next = &sub14;
    sub14.next = &sub23;
    sub23.next = &sub24;
    sub24.next = 0;
 
    bool rtn=false;
    for(Super *p = &sub11; p->next != 0; p = p->next){
        for(Super *q = &sub13; q->next!=0; q = q->next){
            if( p->func( Sub1(*q)) ){
                rtn = true;
                goto out;
        }
out: std::cout<<"hot out!!"<<std::endl;
		}
	}
 
    int i; std::cin >> i;
    return 0;
}

YuO
記事: 941
登録日時: 9年前
住所: 東京都世田谷区

Re: 型が一致しない?

#3

投稿記事 by YuO » 7年前

やりたいことは,ダブルディスパッチでしょうか。基本的には以下のような感じです。

コード:

class super;
class sub1;
class sub2;

class super
{
public:
    virtual void func_main (const super &) const =0;
    virtual void func_sub (const sub1 &) const = 0;
    virtual void func_sub (const sub2 &) const = 0;
};

class sub1 : public super
{
public:
    virtual void func_main (const super &) const override;
    virtual void func_sub (const sub1 &) const override;
    virtual void func_sub (const sub2 &) const override;
};

class sub2 : public super
{
public:
    virtual void func_main (const super &) const override;
    virtual void func_sub (const sub1 &) const override;
    virtual void func_sub (const sub2 &) const override;
};

void sub1::func_main (const super & arg) const
{
    arg.func_sub(*this);
}

void sub2::func_main (const super & arg) const
{
    arg.func_sub(*this);
}

void sub2::func_sub (const sub1 & arg) const
{
    arg.func_sub(*this); // 対称性を維持するために再度入れ替えて呼び出し
}
Visitorパターンがらみで語られる事が多いですが,Visitorに限ったものではないです。
探せば上記のような素朴な実装ではない実装も見つかるかもしれません。
# 初回はsuperを引数にして呼び出し (Dispatch),オーバーライドした関数内で型のわかっている*thisを引数に再度,つまりは計2回呼び出すのでダブルディスパッチ。

adu

Re: 型が一致しない?

#4

投稿記事 by adu » 7年前

ありがとうございました!どっちの方法でもできました!

自前の型変換とデザインパターンですか…

ちなみに,YuO さんの回答にある,メンバ関数のあとに const を付けるのも初見でした.
調べてみると分かりやすいのが英語のサイトしかなかったので確認したいのですが,
func(const sub &arg) const は引数argの変更を許可しないのに対して,
func(const sub &arg) const はfuncを呼び出したインスタンス自身の変更を許可しない
ということでよいのしょうか?

アバター
h2so5
副管理人
記事: 2212
登録日時: 9年前
住所: 東京
連絡を取る:

Re: 型が一致しない?

#5

投稿記事 by h2so5 » 7年前

adu さんが書きました: ちなみに,YuO さんの回答にある,メンバ関数のあとに const を付けるのも初見でした.
調べてみると分かりやすいのが英語のサイトしかなかったので確認したいのですが,
func(const sub &arg) const は引数argの変更を許可しないのに対して,
func(const sub &arg) const はfuncを呼び出したインスタンス自身の変更を許可しない
ということでよいのしょうか?
そうです。
const を付けたメンバ関数の中ではmutableでないクラスメンバの変更及びconstでないメンバ関数の呼び出しができなくなります。

adu

Re: 型が一致しない?

#6

投稿記事 by adu » 7年前

では,サブクラスのメンバ関数が virtual になっているのにはどういう意味があるのですか?
(for式の条件が間違っていました. p->next!=0 ではなく p!=0 です.)

YuO
記事: 941
登録日時: 9年前
住所: 東京都世田谷区

Re: 型が一致しない?

#7

投稿記事 by YuO » 7年前

adu さんが書きました:では,サブクラスのメンバ関数が virtual になっているのにはどういう意味があるのですか?
仮想メンバ関数であることを明示する以上の役割はありません。
仮想メンバ関数をオーバーライドしても仮想メンバ関数なので。
# finalが付いていても,仮想メンバ関数であることは変わらない。

adu

Re: 型が一致しない?

#8

投稿記事 by adu » 7年前

返事が遅れて済みません.
ありがとうございました.

閉鎖

“C言語何でも質問掲示板” へ戻る