是否可以在同一个类中创建一个类的实例?

时间:2016-08-30 10:48:49

标签: c++ c++11

说我有课:

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()时,是否会创建派生类的实例?

4 个答案:

答案 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类的构造函数被调用两次。

  1. 首先,主要是

  2. 中的新B()
  3. 其次是getobj函数调用,它再次创建B

  4. 的对象

答案 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() {}

如前所述,请考虑使用纯虚方法