抛出异常或在基类中返回默认值

时间:2014-07-08 17:25:24

标签: c++

我有一个基类,它将方法定义为虚拟,这些方法内部没有任何内容,只有声明。我有一个派生自基类的类,并没有实现所有方法,这里出现问题。如果我们调用一个未在派生类上实现但在基础上实现的方法,则会崩溃。

示例(崩溃):

#include <iostream>

class Foo
{
public:
    virtual std::string ref() {}
};

class Bar : public Foo {};

int main(int argc, char ** argv)
{
    auto foo = new Bar;
    auto bar = foo->ref();

    return 0;
}

问:在这种情况下,最佳解决方案是什么。

1) - 返回默认(空)值。

virtual std::string ref()
{
    return "";
}

2) - 抛出一个不能直接从基类调用方法的异常。

virtual std::string ref()
{
    throw std::runtime_error(":(");
}

谢谢。

2 个答案:

答案 0 :(得分:4)

这就是纯虚拟用途:

virtual std::string ref() = 0;

现在,编译器不允许您实例化未定义该函数的派生类型的实例。

答案 1 :(得分:2)

  

如果我们调用的方法没有在派生类上实现,但是   在基地,它崩溃。

这并不严格适用于您的示例代码:

virtual std::string ref() {}

有实施;你得到了一个崩溃因为实施没有返回任何东西。这可能会发生在这里,例如:

#include <string>

std::string f() {}

int main()
{
   std::string x = f();
   x = "";
}

(我说&#34;很可能&#34;因为它的未定义行为,所以不能保证崩溃。)

至于你的问题:

如果你需要调用概念上不存在的函数,那么你就会遇到设计问题;很可能你的基类试图同时履行太多的职责。

否则,使用抽象类。您可以通过声明至少一个函数 pure virtual

来使类抽象化
class Foo
{
public:
    virtual std::string ref() = 0; // pure virtual function
};

请注意另外三件事:

  • 您几乎肯定需要在基类中使用虚拟析构函数。
  • 除了析构函数之外,考虑将公共函数设置为非虚拟,将虚拟函数设置为私有,公共非虚拟函数调用私有虚函数。
  • 您的函数看起来像const函数的候选者。

最后的例子:

class Foo
{
public:
    virtual ~Foo() {}
    std::string ref() const { return refImpl(); }
private:
    virtual std::string refImpl() const = 0;
};