正如Scott Myers写的那样,你可以利用C++的类型系统中的松弛来声明clone()返回一个指向所声明的实际类型的指针:
class Base
{
virtual Base* clone() const = 0;
};
class Derived : public Base
{
virtual Derived* clone() const
};
Run Code Online (Sandbox Code Playgroud)
编译器检测到clone()返回指向对象类型的指针,并允许Derived覆盖它以返回指向派生的指针.
希望让clone()返回一个智能指针,它意味着所有权语义的转移,如下所示:
class Base
{
virtual std::auto_ptr<Base> clone() const = 0;
};
class Derived : public Base
{
virtual std::auto_ptr<Derived> clone() const;
};
Run Code Online (Sandbox Code Playgroud)
不幸的是,约定的放宽并不适用于模板化的智能指针,编译器也不允许覆盖.
所以,似乎我有两个选择:
这些方法之一是首选吗?或者有没有办法让我吃掉我的所有权语义转移并且我的强大类型安全呢?
编辑:已解决
我现在正在开发一个多线程项目,我有一个基础工作者类,具有从中继承的不同工作类.在运行时,工作类成为线程,然后根据需要执行工作.
现在,我有一个我写过的Director,它应该维护一个指向所有worker的指针数组,以便它可以从中检索信息,以及稍后修改它们中的变量.
我通过创建指向基类指针的指针来完成此操作:
baseWorkerClass** workerPtrArray;
Run Code Online (Sandbox Code Playgroud)
然后在Director的构造函数中,我动态地为基础worker类分配一个指针数组:
workerPtrArray = new baseWorkerClass*[numWorkers];
Run Code Online (Sandbox Code Playgroud)
在每个工作线程的构造函数中,worker调用director中的一个函数,该函数用于将该worker的指针存储在数组中.
以下是导演存储指针的方式:
Director::manageWorker(baseWorkerClass* worker)
{
workerPtrArray[worker->getThreadID()] = worker;
}
Run Code Online (Sandbox Code Playgroud)
以下是工人变体的示例.每个worker都继承自基类worker类,而base worker类包含纯虚函数,这些函数应该存在于所有worker变量中,以及一些在所有worker之间共享的变量.
class workerVariant : protected baseWorkerClass
{
public:
workerVariant(int id)
: id(id)
{
Director::manageWorker(this);
}
~workerVariant()
{
}
int getThreadID()
{
return id;
}
int getSomeVariable()
{
return someVariable;
}
protected:
int id;
int someVariable
};
Run Code Online (Sandbox Code Playgroud)
然后baseWorkerClass看起来像这样:
class baseWorkerClass
{
public:
baseWorkerClass()
{
}
~baseWorkerClass()
{
}
virtual int getThreadID() = 0;
virtual int getSomeVariable() = 0;
};
Run Code Online (Sandbox Code Playgroud)
在每个worker变量完成初始化之后,我应该得到一个指向baseWorkerClass对象的指针数组.这意味着我应该能够,例如,使用其ID作为数组的索引来获取某个工作中给定变量的值,如下所示: …
以下代码尝试复制对象并保留原始类型.不幸的是它不起作用(每个复制的对象将成为一个Super而不是与其原始的同一个类).
请注意,copySuper(const Super& givenSuper)不应该知道任何关于子类的信息Super.
有可能做这样的副本吗?或者我是否必须更改定义copySuper?
#include <string>
#include <iostream>
class Super
{
public:
Super() {};
virtual ~Super() {};
virtual std::string toString() const
{
return "I'm Super!";
}
};
class Special : public Super
{
public:
Special() {};
virtual ~Special() {};
virtual std::string toString() const
{
return "I'm Special!";
}
};
Super* copySuper(const Super& givenSuper)
{
Super* superCopy( new Super(givenSuper) );
return superCopy;
}
int main()
{
Special special;
std::cout << special.toString() << …Run Code Online (Sandbox Code Playgroud)