说我有课:
class Foo{
public:
Foo(){
}
//Is it possible to create a function like this:
virtual Foo* createOb(){
//Should create a new Foo,Bar or Fiz, depending on the actual object type.
}
}
class Bar: public Foo{
public:
Bar(){
}
}
class Fiz: public Foo{
public:
Fiz(){
}
}
是否可以在基类中使用方法createOb()
,因此当在其中一个派生类的实例上调用createOb()时,是否会创建派生类的实例?
答案 0 :(得分:5)
是的,可以使用CRTP完成。
首先,返回从new
获得的原始指针非常危险。在c++
中,只有在没有指向对象的所有权时才应使用原始指针。所以我冒昧地使用unique_ptr
:
struct Base {
virtual auto create_obj() -> std::unique_ptr<Base>
{
return std::unique_ptr<Base>{};
}
};
// abstract works too:
struct Base {
virtual auto create_obj() -> std::unique_ptr<Base> = 0;
};
template <class Derived>
struct Base_crtp : Base {
auto create_obj() -> std::unique_ptr<Base> override /* final */
{
return std::unique_ptr<Base>{new Derived{}};
}
};
struct D1 : Base_crtp<D1>
{
};
struct D2 : Base_crtp<D2>
{
};
然后:
auto b1 = std::unique_ptr<Base>{new D1{}};
auto b2 = std::unique_ptr<Base>{new D2{}};
auto new_d1 = b1->create_obj();
auto new_d2 = b2->create_obj();
答案 1 :(得分:1)
绝对是!!!
当一个方法在基类中声明为virtual并通过派生类对象调用时,则会调用派生类函数(在c ++中读取vprt,vtable概念)。
#include <iostream>
using namespace std;
class A{
public:
virtual A* getobj(){
return new A();
}
};
class B: public A{
public:
B(){cout<<"B constructor"<<endl;}
virtual A* getobj(){
return new B();
}
};
int main()
{
A *a = new B();
A *second = a->getobj();
return 0;
}
在上面的代码中,我们使用B类对象调用getobj()函数。 这里B类的构造函数被调用两次。
首先,主要是
其次是getobj函数调用,它再次创建B
答案 2 :(得分:0)
不,“纯”继承无法做到这一点。这些类必须覆盖<div ng-app="CMS" ng-controller="CMSCtrl">
myAnimal {{myAnimal}}
<br/> myAction {{myAction}}
<br/>
<form>
<label>Animal</label>
<select ng-model='myAnimal' ng-options="animal for animal in animals" ng-change="callChange()">
<option value="">-- Please Select --</option>
</select>
<label>Action</label>
<select ng-model="myAction" ng-options="action as action.name for action in actions | filter: { usedBy: myAnimal } track by action.id">
<option value="">-- Please Select --</option>
</select>
</form>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
成员函数才能支持克隆。
您可以通过考虑单独编译类来了解为什么这是不可能的。一对一createOb()
成员函数的实现必须与createOb()
和Bar
隔离完成,这使得基类无法知道其子类的类型。
但是在基础中使用纯虚函数的实现很常见。
另一种方法是使用奇怪的重复模板模式(CRTP)来实现克隆。这个article解释了如何做到这一点。
答案 3 :(得分:0)
这不是最佳解决方案,但可行。
在你的.h
class Foo{
public:
Foo();
virtual Foo* createOb();
};
class Bar: public Foo{
public:
Bar();
};
class Fiz: public Foo{
public:
Fiz();
};
在你的.cpp
中#include "Header.h"
Foo::Foo() {}
Foo* Foo::createOb(){
if (dynamic_cast<Bar*>(this)) {
return new Bar();
}
else if (dynamic_cast<Foo*>(this)) {
return new Foo();
}
return nullptr;
}
Bar::Bar() {}
Fiz::Fiz() {}
如前所述,请考虑使用纯虚方法