あなたがそうB
が見るすべてはA
なくAAA
のインスタンスのインスタンスである、B()
コンストラクタに渡されslicing the objectです。
多態性は、仮想メソッドの完全なvtableにアクセスできるように、ポインタ/参照によって派生オブジェクトにアクセスする場合にのみ機能します。また、派生したオブジェクトを渡すときも含まれます。派生クラスを値で基本クラスの変数/パラメータに渡すと、オブジェクトがスライスされ、変数/パラメータは基本クラスのvtableエントリにのみアクセスできます。
ですから、どちらかのように、それに応じてB
を変更する必要があります。
class B
{
public:
B() : obj(0) {} // <-- every constructor needs to initialize members!
B(A *a) : obj(a) {} // <-- accept A by pointer
int Method2(int a, int b) { return (obj) ? obj->Method1(a,b) : 0; }
private:
A *obj;
};
int main() {
A *a = new AAA();
B *b = new B(a); // <-- AAA passed by A* pointer
b->Method2(2,1);
// don't forget these
delete b;
delete a;
return 0;
}
またはこの:
class B
{
public:
B() : obj(0) {} // <-- every constructor needs to initialize members!
B(A &a) : obj(&a) {} // <-- accept A by reference
int Method2(int a, int b) { return (obj) ? obj->Method1(a,b) : 0; }
private:
A *obj;
};
int main() {
A *a = new AAA();
B *b = new B(*a); // <-- AAA passed by A& reference
b->Method2(2,1);
// don't forget these
delete b;
delete a;
return 0;
}
あるいはこの:いずれの場合で
class B
{
public:
// <-- note: no default constructor!
B(A &a) : obj(a) {} // <-- accept A by reference
int Method2(int a, int b) { return obj.Method1(a,b); }
private:
A &obj;
};
int main() {
A *a = new AAA();
B *b = new B(*a); // <-- AAA passed by A& reference
b->Method2(2,1);
// don't forget these
delete b;
delete a;
return 0;
}
、注意してA
は仮想デストラクタを必要とするので、デストラクタはdelete
は、基底クラスA*
ポインタまたはA&
参照に呼び出されます。
class A
{
public:
...
virtual ~A() {} // <-- add this
...
};
あなたがC++ 11以降を使用している場合は、コンパイラは(ド)を処理させ、代わりに生のポインタのstd::unique_ptr
とstd::shared_ptr
を使用する必要がありますあなたのための割り当て:
#include <memory>
class B
{
public:
B(std::shared_ptr<A> &a) : obj(a) {}
int Method2(int a, int b) { return obj->Method1(a,b); }
private:
std::shared_ptr<A> obj;
};
int main() {
std::shared_ptr<A> a(new AAA);
std::unique_ptr<B> b(new B(a));
// or: if you are using C++14 or later:
/*
std::shared_ptr<A> a = std::make_shared<AAA>();
std::unique_ptr<B> b = std::make_unique<B>(a);
*/
b->Method2(2,1);
return 0;
}
参照http://stackoverflow.com/questions/274626/what-is-object-slicing – sakra
'B(A):OBJ(A){}' 'B(あるべきですA&a):obj(&a){} 'そうでなければ、オブジェクトをスライスします。 – AndyG
Bコンストラクタを参照またはポインタでパラメータにする – bisthebis