我知道解决了与此问题相关的问题,但我仍然无法弄清楚如何解决我的问题。
我有这样的事情:
class Base
{
static Base* createBase()
{
Base *b = new Base();
... //does a lot of weird things
return b;
}
}
class Child : public Base
{
static Child* createChild()
{
Child *c = createBase(); // error
return c;
}
}
我知道为什么它不起作用,但我必须找到一种方法来做到这一点。 createBase函数做了很多事情,所以我不想重新编码它。
有什么建议吗?
答案 0 :(得分:9)
为什么你希望这个工作?您不能将Base
对象视为Child
对象,因为Child
类可能包含Base
没有的所有其他数据。
为了获得您正在寻找的效果,有两种方法可以做到:
第一种方式,也许是最好的想法,是将逻辑从createBase
移到Base
构造函数中。无论您是创建Base
还是从中派生的内容,Base
构造函数都会运行。看起来你正在尝试初始化基础对象,而这正是构造函数的用途!
如果由于某些原因这不适用于您的情况,另一个选项是在initialize
中创建受保护的Base
方法,该方法接受Base*
并完成您的所有工作目前正在createBase
进行,例如
class Base
{
public:
static Base* createBase()
{
Base* b = new Base();
initialize(b);
return b;
}
protected:
static void initialize(Base* b)
{
... //does a lot of weird things
}
}
class Child : public Base
{
public:
static Child* createChild()
{
Child *c = new Child();
initialize(c):
return c;
}
}
请注意,这是有效的,因为虽然您无法将Base*
视为Child*
,但您可以走另一条路并对待{{ 1}}就像它是Child*
一样,因为Base*
类由于继承的性质而至少保证Child
类具有的所有内容。
编辑:我看到您在评论中发布了另一个答案,您无法修改Base
的定义。在这种情况下,你完全没有运气,鉴于游戏中的限制,你必须接受复制和粘贴的需要。如果您无法修改其代码,则无法调用Base
并返回指向createBase
以外的任何类型对象的指针。
答案 1 :(得分:2)
为Base类重载new可能会解决您的问题。
类UTIL {
static size_t size;
公共: static void setSize(size_t t) { //互斥保护 size = t; }
static size_t getsize(); // should only be called from inside new of class A
};
A班 { int i;
公共: static A * createA() {
A* a = new A();
a->i = 10;
return a;
}
void * operator new(size_t size)throw(const char *){
void * p = malloc(UTIL :: getsize());
if(p == 0)抛出“分配失败”;
返回p;
}
void operator delete(void * p){
自由(P); }
};
size_t UTIL :: size = sizeof(A);
size_t UTIL :: getsize() {
//mutex protection
size_t tmp = size;
size = sizeof(A);
return tmp;
}
B级 {
公共: int j; static B * createB() {
//take mutex
UTIL::setSize(sizeof(B));
B* b = (B*)(A::createA());
b->j = 20;
//release Mutex
return b;
}
};
答案 2 :(得分:1)
您应该使用
Child *c = new Child();
否则,您正在尝试创建Base类实例并将其称为Child。
重新评论:
也许你可以改变
static Base* createBase();
static void createBase(Base *b);
如果将实例传递给此方法,则可以将它与Child和Base一起使用
例如:
Base *b = new Base();
Base::createBase(b);
Child *c = new Child();
Base::createBase(c);
或者
static Base *createBase(Base *b = NULL){
if(b == NULL){
b = new Base;
}
//do your stuff
return b;
和孩子:
static Child* createChild(){
Child *c = new Child;
createBase(c);
return c;
这样你可以同时使用:
b = Base::createBase();
c = Child::createChild();
答案 3 :(得分:1)
也许您应该按如下方式重新定义createBase:
template< class TheClass > static TheClass* create()
{
TheClass *ret = new TheClass();
... //does a lot of weird things
return ret;
}
然后您可以按如下方式创建对象:
Child* pChild = create< Child >();
这可能不合适取决于“奇怪”的东西,但它是解决问题的一种可能方式。
答案 4 :(得分:1)
“构造函数”中是否存在“怪异”的东西。那么通过构建Child,您的基础是否正确构建了?
否则只需将代码重构为从两个地方调用的方法 - 肯定不要复制它。
答案 5 :(得分:0)
您可以使用构造函数为您完成工作:
class Base
{
Base()
{
// does a lot of weird things
}
static Base* createBase()
{
return new Base();
}
};
class Child : public Base
{
Child()
{
// Do child's weird things here
}
static Child* createChild()
{
return new Child();
}
};
Base *instance1 = new Child(); // Works as expected
Base *instance2 = Child::createChild(); // Works as expected
Base *instance3 = new Base(); // Works as expected
Base *instance4 = Base::createBase(); // Works as expected
修改强>
如果您无法修改Base类,则不应该以这种方式派生它。该类显然意味着具有自己的功能,静态构造方法建议使用更复杂的功能。在这种情况下,您可能希望使用Decorator设计模式而不是继承:http://en.wikipedia.org/wiki/Decorator_pattern
答案 6 :(得分:0)
这个怎么样
class Base
{
public:
static Base* createBase()
{
Base *b = new Base();
//does a lot of weird things
return b;
}
};
class Child
{
protected:
Base* m_basePtr;
public:
operator Base&(){return *m_basePtr;}
static Child* createChild()
{
Child *c=new Child;
c->m_basePtr=Base::createBase();
return c;
}
};
但你必须删除析构函数
的指针答案 7 :(得分:0)
您想要做的是:
class Base
{
Base()
{
... //does a lot of weird things
}
};
class Child : public Base
{
Child Child() // This calls the base constructor auto-magically
{
}
}
int main()
{
Child childOne;
Base baseOne;
Child* childPtr = new Child();
Base* basePtr1 = new Child();
Base* basePtr2 = new Base();
}