【问题标题】:Can I call a function from the base class which return bool from derived class我可以从基类调用一个从派生类返回 bool 的函数吗
【发布时间】:2016-05-31 07:56:14
【问题描述】:

我有以下基类:

class node_layer_manager_t : public layer_manager_t
{
protected:
    //Devices
    trx_t        trx;
private:
    std::vector<string>               trx_dump_labels;

public:
    node_layer_manager_t( xml::node_t& params ); 
    ~node_layer_manager_t();

    virtual bool    set_profile(void) override;    
}

我创建了以下派生类:

class node_layer_manager_with_rad_t : public node_layer_manager_t
{
protected:
    //Devices
    radio_t radio;

public:
    node_layer_manager_with_rad_t(xml::node_t& params );
    ~node_layer_manager_with_rad_t();

    virtual bool    set_profile(void) override;

    virtual void radio_monitoring_job_function(void);

    intervalues_t<double>   radio_tmp;
    ushort          duration_seconds_for_radio_monitoring;
};

我想要它,以便设置配置文件将执行基类的 set_profile 以及其他一些操作。

我可以这样写吗?

bool node_layer_manager_with_rad_t::set_profile(void)
{
    bool success;
    node_layer_manager_t::set_profile();
    try
    {
        string_t profile_tag = "logs/trx_dump/node:"+get_id();
        dev_tx = profile->get_decendant(profile_tag.c_str());
        cout<<"sarit id= "<< get_id()<<endl;
        success = true;
    }
    catch(...)
    {
        cout<<"sarit  profile error: "<<endl;
        success = false;
    }
    return success;  //**
}

**或者我应该重复以下内容:

return (success && node_layer_manager_t::set_profile()); 

【问题讨论】:

  • 这是关于 C++ 还是关于您的特定设计的问题?如果是前者,您只应该编写一个不违反语言规则的程序。在这方面,您的两个变体看起来都不错。如果是后者,如果不完全了解设计,任何人都不可能有任何想法。试探性地,第二个变体看起来更有希望(虽然在 setter 中打印看起来很可疑)。

标签: c++11 inheritance


【解决方案1】:

如果您必须调用父类set_profile,无论您必须在派生类中做什么,您都应该采用关注此约束的设计。

通常,您应该将基类set_porfile 标记为final 并管理基类内部专用派生类方法的调用:

class node_layer_manager_t : public layer_manager_t
{
protected: 
    ....
    // set_profile actions of derived class
    // proposed a default without side effect implementation if
    // derived class doesn't need to overload this.
    virtual bool set_profile_child() { return true; };
private:
    ....
public:
    .....
    // Manage here call of derived
    virtual bool set_profile() override final
    {
        // actions before derived specific actions
        ....
        // Call specific derived class actions
        bool success = set_profile_child();

        // actions after derived specific actions
        if (success)
        {
            //do based class action
        }
        return success;
    }
}

在孩子中:

class node_layer_manager_with_rad_t : public node_layer_manager_t
{
protected:
    ....

public:

    virtual bool    set_profile_child() override;
};

// Manage only there own action, regardless of needs of based class
bool node_layer_manager_with_rad_t::set_profile(void)
{
    try
    {
        // Do what you're in charge, and only what you're in charge!
    }
    catch(...)
    {
        cout<<"sarit  profile error: "<<endl;
        success = false;
    }
    return success;  //**
}

通过这种设计,每个班级只做它必须管理的事情,而且只做它自己的事情。派生类不必处理基类的需求。

如果您想为派生类提供决定代码是在泛型行为之前还是之后执行的能力,您可以替换或添加set_profile_child() 两种方法:bool pre_set_profile()bool post_set_profile()

【讨论】:

  • 这是一个很好的方法 (+1),但也不是圣杯。您决定何时执行子类的代码,所以像class Sub1::do() { doSomething(); Super::do(); } class Sub2::do() { Super::do(); doSomethingDifferent(); } 这样的事情变得不可能......
  • @Aconcagua 如果你需要这种行为,你可以用bool pre_set_profile()bool post_set_profile()替换bool set_profile_child()(或者有这3种方法)
  • 嗯,这可能是一个不好的答案,因为我并没有真正考虑这一点,但首先想到的答案是:如果基类允许派生类管理异常,则基类必须提供正确的接口 => 添加virtual void handle_set_profile_expection(TheException &amp;e)
  • (哦,已经删除了我的 cmets,我自己也一样回答了......)。我的版本是if(!handle(TheException&amp; e)) throw;,所以结果是布尔值。但我认为我们已经找到了问题所在:任何时候你没有预见到派生类在你的基类中已经需要的行为,你必须修改两者。在某些情况下,付出这个代价是绝对值得的(这就是我赞成的原因——我仍然知道基类代码必须执行的先决条件),但在其他情况下更简单或更高效(考虑高性能代码)只是为了让覆盖外部函数。
  • 这与我在自己的回答中所写的类似:一切都取决于您对结果施加(或被施加)的要求......
【解决方案2】:

一开始,你还没有在任何地方声明成功(所以实际上,这不是mcve,代码不应该按原样编译)。

我还是明白了 - 答案是:这取决于你真正想要做什么......

你想先调用超类还是在子类代码后调用?你的例子暗示前者,你的选择是后者。如果超类函数失败或者仍然执行你的代码,你想中止吗?

您的初始示例调用超类函数,忽略结果并在之后执行自己的操作。

这会首先调用超类函数,并仅在成功时继续:

bool success = node_layer_manager_t::set_profile();
if(success)
{
    try { /*...*/ } // <- no need to set success to true, it is already
    catch(...) { /*...*/ success = false; }
}

这两个都执行,但合并结果:

bool success = node_layer_manager_t::set_profile();
try { /*...*/ } // <- do not modify success, must remain false if super class failed!
catch(...) { /*...*/ success = false; }

如果没有出错,您可以先执行子类代码并仅调用超类函数的替代提示。

这些方法中的任何一种都可能是合适的,但可能都不合适。您必须清楚地了解您的需求是什么 - 然后实现代码以满足您的需求......

【讨论】:

  • 是否可以用覆盖权声明两个 set_profile(2 个类)?
  • here:是的,没关系(前提是layer_manager_t也有这样的虚函数!)。
猜你喜欢
  • 2014-04-30
  • 1970-01-01
  • 2011-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-08
  • 2019-07-16
  • 1970-01-01
相关资源
最近更新 更多