我正在使用以下使用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
类型的成员对象后,我将其传递给接收func
的函数Base
,并且应该使用多态性调用成员foo
的正确var
。
问题: 的(1) 在上面的变体中,编译器抱怨:
overriding 'virtual std::shared_ptr<Member> Base::get_var()'
get_var() {return var;}`
(2)
如果我评论ChildBase
get_var
的实现,则此函数将被视为Base
,从而返回指向Member
但没有foo2
的指针。
(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();
} */
}
EDIT2 在下面添加了答案。
答案 0 :(得分:1)
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-qualification和类类型 与B :: f的返回类型中的类类型具有相同的cv资格或更少的cv资格。
您的情况下所有条件都失败了。您可以使用原始指针或引用,例如http://liveworkspace.org/code/4eQWBI $ 1
但我认为你应该重写你的界面而不是使用foo2
,如果它不是虚拟的。
答案 1 :(得分:1)
要解决您的问题,请参阅此代码的修改和注释版本:
#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);
}
答案 2 :(得分:1)
由于覆盖函数的返回类型不能有所不同,我将使用动态强制转换来实现解决方案。因此,不需要为`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
}
答案 3 :(得分:0)
shared_ptr
不是指针,因此协方差不适用。
通常情况下,我对协方差的使用持怀疑态度。一世 通常会发现派生类更清晰,不会改变 返回类型,并在需要时提供新功能 返回指向派生函数的指针。在你的情况下,我会说 这是必不可少的,因为你实际上有两个指针 (最终可能指向不同的对象)。
答案 4 :(得分:0)
过了一会儿,我虽然以下代码可能是一个很好的解决方案:
#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 lvl的继承。
输出结果为:
unique foo in child 1
Child Member 1
Child Member 2
Child-Child Member 2