【问题标题】:Overloading Getters In C++?在 C++ 中重载吸气剂?
【发布时间】:2013-04-20 20:05:30
【问题描述】:

早安,

我不确定如何用一句话正确描述我所询问的过程,所以请原谅标题。我正在寻找一种方法来确保基类和/或接口的用户会以非默认方式分配对象本身和其他对象会考虑的数据。所以我一直在做以下事情:

struct ExampleInterface {
    virtual void SomeMethod() = 0;
    virtual std::string WhatLooksLikeAGetterButIsNot() = 0;
};

这是一个真实的例子:

//So states can be "poped in and out".//
struct State
{
    //To retrive what the active state is called.//
    /*Code In Question--->*/virtual std::string RegardStateAs() = 0;/*<---Code In Question*/
    virtual void ExecuteState( VRGE::MDNode* metaData ) = 0;
};

我们的想法是最终做一些事情,例如 A(如果有人从“更新”派生,此选项允许尝试阻止问题发生):

struct Update : public State
{
    //Yadda yadda...//
    /*Code In Question--->*/std::string RegardStateAs() {
                                return std::string{ "Update" };
                            }/*<---Code In Question*/
};

B(此选项不允许 A 做的事情):

struct Update : public State
{
        //Yadda yadda...//
        //Not a good example, but the point gets across.//
        Update( std::string value ) {
            stateName = value;
        }
        /*Code In Question--->*/virtual std::string RegardStateAs() {
                                        return stateName;
                                 }/*<---Code In Question*/
            private: 
               std::string stateName;

};

我的问题是:这是好的还是坏的做法?

-----编辑-----:

我无法访问可以编译它的编译器,但是有人向我指出,在这种情况下“覆盖”将是完美的,例如:

//So states can be "poped in and out".//
struct State
{
    //To retrive what the active state is called.//
    /*Code In Question--->*/virtual std::string RegardStateAs() = 0;/*<---Code In Question*/
    virtual void ExecuteState( VRGE::MDNode* metaData ) = 0;
};

struct Update : public State
{
    //Yadda yadda...//
    /*Code In Question--->*/std::string RegardStateAs() override {
                                return std::string{ "Update" };
                            }/*<---Code In Question*/
};

【问题讨论】:

  • 使用override会更好
  • 这个问题我无法回答,但是匹配基类的虚函数的函数是隐式虚函数,即使派生类不使用关键字。
  • @CaptainObvlious 我没想到!谢谢!
  • @BenVoigt 我认为他要求作为一种风格问题来传达成员函数覆盖基本实现。
  • 问题是......返回成员时返回从文字构造的 std::string 是否比成员的副本更好?否则我只剩下本在说嗯?

标签: c++ oop c++11 coding-style


【解决方案1】:

正如其他人指出的那样,您的问题实际上是解决“覆盖”(在多态意义上),而不是“重载”。

假设您希望每个 State 子类(静态)都有一个固定标签,那么您的策略是可行的,但存在一些限制。为清楚起见,我将您的“RegardAsState”称为“ToString”。如果需要在基类State的构造函数中调用ToString,就会有问题。这是因为在执行基类构造函数时,尚未建立派生类(如 Update)的 ToString 的 v-table 条目。在 State 的析构函数中调用 ToString 也存在类似的问题。

另一种方法是简单地将状态标签实现为基类 State 中的 const std::string,并通过公共 get 访问器通过 const std::string & 返回它。它更有效一点,既消除了 v-table 间接,又允许通过 const ref 返回;并且它消除了 State 中的上述 ctor/dtor 问题。

即使上面的建议也不是最优的,因为如果每个不同的 State 子类的标签都相同,则无需将此作为实例方法。如果您想获得异国情调,您可以将 ToString 实现为静态(无状态)访问器。这可以通过一个鲜为人知的技巧来完成,将常量字符串作为模板参数传递,如下所示:

template<const std::string & label>
struct State
{
    static const std::string & ToString()
    {
        return label;
    }
};

extern const std::string UpdateLabel = "Update";
State<UpdateLabel> Update;

// Or, with a bit of help from the macro preprocessor
#define DEFINE_STATE(stateClass) \
extern const std::string stateClass##Label = #stateClass; \
struct stateClass##State : State<stateClass##Label> \
// continue with definition of stateClass##State ... {}

DEFINE_STATE(Sample)
{
    // implementation of SampleState
};

【讨论】:

  • 感谢您的回复。抱歉,我花了这么长时间才看到它。只是几个问题:1:我不确定你在这里的意思“假设你想要一个固定的标签为每个状态子类(静态)”,特别是静态这个词,你指的是使某物成为静态,还是这样的事实标签将是不可变的。 2:如果我继承自State,并且状态标签是const,在子类中是不是不能改?
  • 3:您能告诉我您在哪里学习如何在使用预处理器 XD 时成为老板吗? P.s 我没有尝试对该方法进行构造函数/析构函数调用。
  • 我刚刚又看了一遍,我认为这是个好主意,我对它使用新功能有一些额外的想法。
猜你喜欢
  • 2014-02-24
  • 1970-01-01
  • 2018-11-16
  • 1970-01-01
  • 2018-04-05
  • 2013-06-07
  • 2019-11-26
  • 2017-09-28
  • 1970-01-01
相关资源
最近更新 更多