4

在虚拟构造函数习语中,有一些虚拟函数使用虚拟函数返回新对象或对象的副本。但是要以多态方式调用这些虚函数,您必须使用实际构造函数创建该类的对象。

在设计模式上下文中,这意味着客户端在使用多态对象创建方式之前就知道对象的类型?

4

4 回答 4

6

客户不一定要知道具体类型。例如,考虑这个层次结构:

struct Base
{
    virtual ~Base();
    virtual Base * clone() const = 0;
    static Base * create(std::string const &);
    // ...
};

struct A : Base { A * clone() const { return new A(*this); } /* ... */ };
struct B : Base { B * clone() const { return new B(*this); } /* ... */ };
struct C : Base { C * clone() const { return new C(*this); } /* ... */ };

Base * Base::create(std::string const & id)
{
    if (id == "MakeA") return new A;
    else return new C;
};

在这种情况下,客户端可以像这样创建和复制现有对象:

Base * p = Base::create("IWantB");  // or std::unique_ptr<Base> !
Base * q = p->clone();

在这两种情况下,客户端都不知道*por的动态类型*q

于 2012-07-20T06:48:53.523 回答
2
class Base
{
public:
    Base() { }

    virtual ~Base() { }

    // The "Virtual Constructor"
    static Base *Create(int id);

    // The "Virtual Copy Constructor"
    virtual Base *Clone() = 0;
};

Base *Base::Create(int id)
{

    if( id == 1 )
    {
        return new Derived1;
    }
}

class Derived1 : public Base
{
public:
    Derived1()
    {
        cout << "Derived1 created" << endl;
    }

    Derived1(const Derived1& rhs)
    {
        cout << "Derived1 created by deep copy" << endl;
    }

    ~Derived1()
    {
        cout << "~Derived1 destroyed" << endl;
    }

    Base *Clone()
    {
        return new Derived1(*this);
    }
};

当你这样做时,现在在 Main

void main()
{
        cout << "Enter ID (1, 2 or 3): ";
        cin >> input;
        Base *pBase = Base::Create(input);
        Base *pCopy = CreateCopy(pBase);

        //Dont know what object is created but still access functions thru base pointer
}

Base *CreateCopy(Base *pBase)
{
  return pBase->Clone();
}

客户端不需要知道它继承的类的类型,但仍然调用一些函数。

于 2012-07-20T06:48:01.597 回答
1

客户端知道派生类型的虚拟构造函数习语。这个习语的全部目的是通过基指针克隆对象。这是一个例子:

class base
{
public:
   base* clone()
   {
       // NVI: implemented by derived classes.
       do_clone();
   }

 protected:
   virtual base* do_clone = 0;
};

class derived : public base
{
protected:
    virtual derived* do_clone()
    {
        // Implementation. Note the return value is not base*.
    }
 };

有关详细信息,请参阅这篇 ACCU 文章:http: //accu.org/index.php/journals/522

于 2012-07-20T06:49:19.193 回答
0

最终,某处必须知道您的对象的具体类型。隐藏该细节的想法导致了一种称为控制反转的模式,或者最近称为依赖注入

想法是在整个程序中指定一个组件,该组件知道所使用的具体类型。然后,该组件负责组装您的对象图;其他组件仅将其依赖项作为接口,在构造或方法中传递。

有一些 C++ 的依赖注入器实现:我想到了 spring-cpp、fallframework 和 dicpp。我自己编写了一个,名为sauce,它模仿名为guice的 java 框架的风格。

于 2012-07-20T06:49:00.410 回答