【问题标题】:Inheritance and cast继承和演员表
【发布时间】:2012-08-20 18:28:13
【问题描述】:

我在使用 C++ 进行类转换时遇到了一些问题。
为了学习,我想创建一个只进行运算的类,比如求和,但每次启动它似乎都会崩溃。

这是我的简单课程:

#include <iostream>


class CCalculation {
public:
CCalculation() {};
virtual int calculate() = 0;
};


class CCalc_CONST : public CCalculation {
    int x;
public:
    CCalc_CONST(int a) : x(a) {};
    int calculate() { return x; };
};    


class CCalc_ADD : public CCalculation {
    CCalculation *x;
    CCalculation *y;
public:
    CCalc_ADD(CCalculation *a, CCalculation *b) {
        this->x = a;
        this->y = b;
    };
    int calculate() {
        std::cout << "Calculation...\n";
        return x->calculate() + y->calculate();
    };
};

我的测试:

    CCalculation *a = &CCalc_CONST(4);
    CCalculation *b = &CCalc_CONST(1);
    CCalculation *c = &CCalc_ADD(a,b);

    std::cout << "res: " << c->calculate() << "\n";

似乎每次都崩溃(我没有收到编译器错误或警告)。 我发现运行它的唯一方法是在 CCalc_ADD 构造中打印 a->calculate 和 b->calculate 时。我完全不知道为什么我需要调用计算函数才能使其工作。

有人可以向我解释一下具体怎么做吗?

【问题讨论】:

  • 指针越少越好。并且编译器应该警告您获取临时地址。它们不会停留足够长的时间让您使用它们。

标签: c++ class inheritance casting parent-child


【解决方案1】:

首先,您应该打开所有警告(请参阅您的编译器的文档,gcc-Wall

然后你会看到,你的编译器会责备你:

1.cpp: In function 'int main()':
1.cpp:56:37: error: taking address of temporary [-fpermissive]
1.cpp:57:37: error: taking address of temporary [-fpermissive]
1.cpp:58:37: error: taking address of temporary [-fpermissive]

其实在这里

CCalculation *a = &CCalc_CONST(4);

您只需创建临时对象,该对象将在创建后立即销毁,并且您会得到损坏的指针。

你有两个选择:

  1. 在动态内存中创建对象(但在这种情况下我会建议让复杂的计算所有者更简单)

    class CCalc_ADD : public CCalculation {
        std::unique_ptr<CCalculation> x;
        std::unique_ptr<CCalculation> y;
    public:
        CCalc_ADD(CCalculation *a, CCalculation *b):x(a), y(b)
        {
        };
        int calculate() {
            std::cout << "Calculation...\n";
            return x->calculate() + y->calculate();
        };
    };
    
    
    std::unique_ptr<CCalculation> a(new CCalc_CONST(4));
    //... 
    CCalc_ADD c (std::move(a), std::move(b));
    
  2. 用引用替换指针。然后你可以使用值语义。

【讨论】:

    【解决方案2】:

    要获得一个工作程序,您甚至不需要使用new

    CCalc_CONST a(4);
    CCalc_CONST b(1);
    CCalc_ADD   c(&a,&b);
    
    std::cout << "res: " << c.calculate() << "\n";
    

    【讨论】:

      【解决方案3】:

      您没有使用新的。像这样测试:

      CCalculation *a = new CCalc_CONST(4);
      CCalculation *b = new CCalc_CONST(1);
      CCalculation *c = new CCalc_ADD(a,b);
      

      您可以通过使用-Wall 编译来清除临时对象上的address-of 之类的东西,这会启用所有编译器警告。编译器是您的朋友,可以提供帮助。喜欢编译器。

      【讨论】:

      • 解决方案太简单了,我有点难过。非常感谢,下次试试-Wall。
      • 你一次读一页书,而不是一次把整本书塞进喉咙里。
      【解决方案4】:

      您正在尝试访问不再存在的临时对象。使用运算符new 为对象分配内存并调用其构造函数。

      CCalculation *a = new CCalc_CONST(4);
      CCalculation *b = new CCalc_CONST(1);
      CCalculation *c = new CCalc_ADD(a,b);
      

      我已经用 GCC 进行了尝试,它对此发出了非常明确的警告:

      test.cpp: In function ‘int main()’:
      test.cpp:35:33: error: taking address of temporary [-fpermissive]
      test.cpp:36:37: error: taking address of temporary [-fpermissive]
      test.cpp:37:37: error: taking address of temporary [-fpermissive]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-13
        • 1970-01-01
        • 2010-12-13
        • 2012-04-12
        相关资源
        最近更新 更多