类及其成员的继承和多态性(shared_ptr,C++11)
inheritance and polymorphism for class and its member at the same time (shared_ptr, C++11)
我正在处理以下使用std::shared_ptr(C++11(的类结构:
#include <string>
#include <iostream>
#include <vector>
#include <memory>
//class Member is given by a 3rd party library, CAN'T modify its structure!
class Member {//no instance of this class allowed
public:
Member() {};//should never be called
virtual ~Member() = 0;//pure virtual distructor;
virtual void foo() {
std::cout<<"Member"<<std::endl;
}
};
Member::~Member() {} //need to define destructor because of child classes
class ChildMember : public Member {
public:
ChildMember() {};
virtual void foo() {
std::cout<<"Child Member"<<std::endl;
}
virtual void foo2() {
std::cout<<"unique foo in child"<<std::endl;
}
};
class Base {
public:
Base() {};
virtual
std::shared_ptr< Member >
get_var() {return var;}
virtual void
set_var ( std::shared_ptr< Member > v) { var = v;}
std::shared_ptr< Member > var;
};
class ChildBase : public Base {
public:
ChildBase() {
//var = std::make_shared<ChildMember>();
};
virtual
std::shared_ptr< ChildMember >
get_var() {return var;} //(2) : try to comment
virtual void
set_var ( std::shared_ptr< ChildMember > v) { var = v;}
std::shared_ptr< ChildMember > var;
};
void func(std::shared_ptr<Base> b) {
b->get_var()->foo();// process input using polymorphism
}
int main()
{
std::shared_ptr<ChildBase> cb( std::make_shared<ChildBase>());
cb->set_var (std::make_shared<ChildMember>() );
cb->get_var()->foo2();//(3) want to use unique functions of ChildBase;
cb->var->foo2(); //can access directly as well;
//cb->var = std::make_shared<ChildMember>();
func(cb);
}
我尝试设计两个类(Base
和ChildBase
(,其中每个类都有自己的成员Member
/ChildMember
。在完全使用ChildBase
对象及其类型为ChildMember
的成员对象后,我将其传递给接收Base
的函数func
,并且应该使用多态性调用成员var
的适当foo
。
问题:(1(在上面的变体中,编译器抱怨道:
overriding 'virtual std::shared_ptr<Member> Base::get_var()'
get_var() {return var;}`
(2(如果我注释掉get_var
的ChildBase
实现,则此函数被视为Base
,并因此返回指向没有foo2
的Member
的指针。
(3(我也可以评论cb->get_var()->foo2()
。所有的东西都编译了,但似乎没有调用ChildMember::foo()
,因为没有输出Child Member
;
有些事情(希望(有点乱,但我不知道是什么。你们能帮忙纠正一下吗?
EDIT1:
基于Abhijit Kadam的回答,以下代码完全编译:
#include <string>
#include <iostream>
#include <vector>
#include <memory>
class Member {//no instance of this class allowed
public:
Member() {};
virtual ~Member() = 0;//pure virtual distructor;
virtual void foo() {
std::cout<<"Member"<<std::endl;
}
};
Member::~Member() {} //need to define destructor for child classes
class ChildMember : public Member {
public:
ChildMember() {};
virtual void foo() {
std::cout<<"Child Member"<<std::endl;
}
void foo2() {
std::cout<<"unique foo in child"<<std::endl;
}
};
class Base {
public:
Base() {};
std::shared_ptr< Member >
get_var() {return var;}
void set_var ( std::shared_ptr< Member > v) { var = v;}
std::shared_ptr< Member > var;
};
class ChildBase : public Base {
public:
ChildBase() {
//var = std::make_shared<ChildMember>();
};
std::shared_ptr< ChildMember > var;
};
void func(std::shared_ptr<Base> b) {
b->get_var()->foo();// process input using polymorphism
}
void func_vec( std::vector<
std::shared_ptr<Base>
> vec) {
for (unsigned int i=0;i<vec.size();i++)
vec[i]->get_var()->foo();
}
int main()
{
std::shared_ptr<ChildBase> cb( std::make_shared<ChildBase>());
cb->set_var (std::make_shared<ChildMember>() );
func(cb);
std::vector< std::shared_ptr<Base>> vec;
vec.push_back(cb);
func_vec(vec);
cb->var->foo2();
/*std::shared_ptr<ChildMember> ptr(std::dynamic_pointer_cast<ChildMember>(cb->get_var()) );
if (ptr) {
ptr->foo2();
} */
}
编辑2在下面添加了一个答案。
由于重写函数的返回类型不能不同,我将使用动态转换来实现该解决方案。因此,"get_var和set_var"不需要具有虚拟函数。此外,foo2不需要是虚拟的,除非该类将由其他类进一步派生。
int main()
{
std::shared_ptr<ChildBase> cb( std::make_shared<ChildBase>());
cb->set_var (std::make_shared<ChildMember>() );
shared_ptr<ChildMember> ptr(dynamic_pointer_cast<ChildMember>(cb->get_var()) );
if (ptr) {
ptr->foo2();
}
}
class Member {//no instance of this class allowed
public:
Member() {};
virtual ~Member() = 0;//pure virtual distructor;
virtual void foo() {
std::cout<<"Member"<<std::endl;
}
};
Member::~Member() {} //need to define destructor for child classes
class ChildMember : public Member {
public:
ChildMember() {};
virtual void foo() {
std::cout<<"Child Member"<<std::endl;
}
void foo2() {
std::cout<<"unique foo in child"<<std::endl;
}
};
class Base {
public:
Base() {};
std::shared_ptr< Member >
get_var() {return var;}
void set_var ( std::shared_ptr< Member > v) { var = v;}
std::shared_ptr< Member > var;
};
class ChildBase : public Base {
public:
ChildBase() {
//var = std::make_shared<ChildMember>();
};
std::shared_ptr< ChildMember > var;
};
void func(std::shared_ptr<Base> b) {
b->get_var()->foo();// process input using polymorphism
}
virtual
std::shared_ptr< Member >
get_var() {return var;}
virtual
std::shared_ptr< ChildMember >
get_var() {return var;} //(2) : try to comment
压倒一切是错误的。n3337 10.3/7
重写函数的返回类型应与重写的返回类型相同函数或协变函数的类。如果函数D::f覆盖函数B::f,则如果函数的返回类型满足以下条件,则它们是协变的:
--两者都是指向类的指针,都是对类的左值引用,或者都是对的右值引用类
--返回类型B::f中的类与返回类型D::f的类是同一类,或者是D::f 返回类型中类的明确且可访问的直接或间接基类
--两个指针或引用在D::f的返回类型中具有相同的cv限定和类类型具有与B::f的返回类型中的类类型相同或更少的cv资格
在您的情况下,所有条件都会失败。您可以使用原始指针或引用,例如http://liveworkspace.org/code/4eQWBI1美元但我认为你应该重写你的接口,不要使用foo2
,如果它不是虚拟的。
要解决您的问题,请参阅代码的修改和注释版本:
#include <string>
#include <iostream>
#include <vector>
#include <memory>
class Member {//no instance of this class allowed
public:
Member() {};
virtual ~Member() = 0;//pure virtual distructor;
virtual void foo() {
std::cout<<"Member"<<std::endl;
}
};
Member::~Member() {} //need to define destructor for child classes
class ChildMember : public Member {
public:
ChildMember() {};
virtual void foo() {
std::cout<<"Child Member"<<std::endl;
}
virtual void foo2() {
std::cout<<"unique foo in child"<<std::endl;
}
};
class Base {
public:
Base() {};
// maybe you should have a virtual dtor here
virtual ~Base();
// note: NOT virtual
std::shared_ptr< Member >
get_var() {return var;}
// also NOT virtual
void set_var ( std::shared_ptr< Member > v) { var = v;}
std::shared_ptr< Member > var;
};
class ChildBase : public Base {
public:
ChildBase() {
//var = std::make_shared<ChildMember>();
};
// non-virtual version which casts var to the correct type
std::shared_ptr< ChildMember >
get_var() {return std::dynamic_pointer_cast<ChildMember>(var);}
// note: no var here, use the one from Base
};
void func(std::shared_ptr<Base> b) {
b->get_var()->foo();// process input using polymorphism
}
int main()
{
std::shared_ptr<ChildBase> cb( std::make_shared<ChildBase>());
cb->set_var (std::make_shared<ChildMember>() );
cb->get_var()->foo2();//(3) want to use unique functions of ChildBase;
// This can't work:
//cb->var->foo2(); //can access directly as well;
//cb->var = std::make_shared<ChildMember>();
func(cb);
}
shared_ptr
是而不是指针,因此协方差不适用。
通常,我对协方差的使用持怀疑态度。我通常会发现派生类不更改更干净返回类型,并在需要时提供一个新函数返回指向派生函数的指针。在你的情况下,我想说这是至关重要的,因为你实际上有两个指针(最终可能指向不同的对象(。
#include <string>
#include <iostream>
#include <vector>
#include <memory>
class Member {//no instance of this class allowed
public:
Member() {};
virtual ~Member() = 0;//pure virtual distructor;
virtual void foo() {
std::cout<<"Member"<<std::endl;
}
};
Member::~Member() {} //need to define destructor for child classes
class ChildMember1 : public Member {
public:
ChildMember1() {};
virtual void foo() {
std::cout<<"Child Member 1"<<std::endl;
}
void foo1() {
std::cout<<"unique foo in child 1"<<std::endl;
}
};
class ChildMember2 : public Member {
public:
ChildMember2() {};
virtual void foo() {
std::cout<<"Child Member 2"<<std::endl;
}
};
class ChildChildMember2 : public ChildMember2 {
public:
ChildChildMember2() {};
virtual void foo() {
std::cout<<"Child-Child Member 2"<<std::endl;
}
};
class Base {
public:
Base() {};
virtual
~Base() {};
virtual
std::shared_ptr< Member >
get_var() = 0; //purely abstract class
};
class ChildBase1 : public Base {
public:
ChildBase1() {
var = std::make_shared<ChildMember1>();
};
virtual
std::shared_ptr< Member >
get_var() {return var;}
std::shared_ptr< ChildMember1 > var;
};
class ChildChildBase : public ChildBase1 {
public:
ChildChildBase() {
var2 = std::make_shared< ChildChildMember2>();
}
virtual
std::shared_ptr< Member >
get_var() { return var2; }
std::shared_ptr< ChildChildMember2 > var2;
};
class ChildBase2 : public Base {
public:
ChildBase2() {
var = std::make_shared<ChildMember2>();
};
virtual
std::shared_ptr< Member >
get_var() {return var;}
std::shared_ptr< ChildMember2 > var;
};
void func(std::shared_ptr<Base> b) {
b->get_var()->foo();// process input using polymorphism
}
int main()
{
std::shared_ptr<ChildBase1> cb1( std::make_shared<ChildBase1>());
cb1->var->foo1();
func(cb1);
std::shared_ptr<ChildBase2> cb2( std::make_shared<ChildBase2>());
func(cb2);
std::shared_ptr<ChildChildBase> ccb( std::make_shared<ChildChildBase>());
func(ccb);
}
我认为它实现了我所追求的,没有并行继承或动态铸造。它还有超过1级的继承。
输出为:
unique foo in child 1
Child Member 1
Child Member 2
Child-Child Member 2
- CLANG 编译器 说:变量"PTR"可能未初始化
- 在以唯一ptr为值的C++映射中,动态内存何时会被销毁
- 将 ptr 传递给 ptr 到 A 作为参数传递给 A 的函数是不好的做法吗?
- 为共享 ptr 向量实现复制 c'tor?
- 字符和整数中 **(ptr+1) 的值差异
- C++:在不中断共享的情况下通过引用传递共享 PTR?
- 如何将派生类从基 ptr 分配给 nlohmann::json
- 引用 std::shared:ptr 以避免引用计数
- 为什么我不能在不进行任何转换的情况下将浮点数放入任何类型的 ptr 中?
- 在调用函数时,ptr** 和 ptr*& 之间是否有区别,或者首选C++?
- 另一种类型的智能ptr,比如具有弱refs的unique_ptr
- 尝试打印出 *ptr++ 的值,以了解它是如何工作的
- 如何控制共享 ptr 引用计数?
- dopen():不以 root 身份运行时"failed to map segment from shared object"
- C++中的指针否定 (!ptr == NULL)
- 从const ptr*转换为ptr*时出现问题
- 无法使用 libtool 将 -shared 参数传递给 g++
- boost::shared_ptr和std::shared-ptr的同居
- 我可以用std::shared_ptr而不是boost::shared-ptr构建boost库吗
- shared-ptr-C++shared_ptr与unique_ptr用于资源管理