我编写了一个使用继承的程序,一切都还可以,但我认为不应该自然而然地出现错误。 这是我的计划:
class A
{
protected:
int x;
public:
A(){};
~A(){};
A* operator=(const A* other)
{
this->x = other->x;
return this;
}
};
class B : public A
{
public:
B() : A(){};
~B(){};
};
class C
{
protected:
A *a;
public:
C(const A* other){ *(this->a) = other; };
};
int main()
{
B *b = new B();
C *c = new C(b);
return 0;
}
它在语句中产生执行时间错误' this-> x = other-> x;'。 那怎么样?
答案 0 :(得分:7)
*(this->a)
是未定义的行为,因为this->a
未初始化 - 它只是一个悬空指针。
您可以使用a = new A; *a = other
(在这种情况下this->
是多余的),但这不是正确的C ++方式 - 您应该使用RAII(查找它) - 您不需要析构函数,赋值运算符或复制构造函数,如果你这样做的话。
此外,operator =
通常会通过引用返回*this
。
答案 1 :(得分:2)
我喜欢Luchian的答案,但代码中仍有一些地方需要增强,在修复其他潜在错误之前,您可能仍会在代码中遇到一些未定义的行为。
class A
{
protected:
int x;
public:
A():x(0){} // should always initialize x in constructor
virtual ~A()=0 {} // as A is a base case, ~A must be virtual
A& operator=(const A& other) // a reference will be more practical better?
{
this->x = other.x;
return *this;
}
};
如果您不想制作B对象,这意味着B作为基类提供服务,您应该将其析构函数设置为虚拟,甚至使其成为纯虚拟对象。
class B : public A
{
public:
B() : A(){}
virtual ~B(){} =0
{ }
};
Luchian已经回复了{p> *(this->a) = other;
。在你的代码中,如果你想保留一个指向A的指针副本,你只需在member initialize list
中初始化a_ptr即可。
见下面的演示代码:
class C
{
protected:
A *a_ptr;
public:
C(A* other):a_ptr(other){ }
};
最后来到你的main函数,如果b,c只在main函数中使用,当程序完成时,系统将声明动态分配的内存,但如果在循环中使用a,b
,则需要删除他们手动。