2

我编写了一个使用继承的程序,一切正常,但我认为自然不应该出现错误。这是我的程序:

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;”中产生执行时间错误。那这个呢?

4

2 回答 2

7

*(this->a)是未定义的行为,因为this->a没有初始化 - 它只是一个悬空指针。

你可以使用a = new A; *a = otherthis->在这种情况下是多余的),但这不是正确的 C++ 方式——你应该使用 RAII(查找它)——如果你这样做了,你就不需要析构函数、赋值运算符或复制构造函数。

此外,operator =通常*this通过引用返回。

于 2012-12-28T22:47:13.013 回答
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
    { }       
};

*(this->a) = other;Luchian已经回答了。在您的代码中,如果您想保留指向 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在循环中使用,你需要手动删除它们。

于 2012-12-28T23:15:43.327 回答