C++ 告诉子类对超类做些什么是一种好的实践(可能是一些已知的设计模式?)吗';受保护的变量是什么?

C++ 告诉子类对超类做些什么是一种好的实践(可能是一些已知的设计模式?)吗';受保护的变量是什么?,c++,C++,这是一个好的模式吗 BaseClass { protected: Data m_data; public: Interesting public_method() { //returns something interesting about m_data //what exactly depends on what the subclass put into m_data } } DerivedClass { public: DerivedClass() {

这是一个好的模式吗

BaseClass {
protected:
  Data m_data;
public:
  Interesting public_method() {
    //returns something interesting about m_data
    //what exactly depends on what the subclass put into m_data
  }
}

DerivedClass {
public:
  DerivedClass() { //properly populate m_data }
}

这个缺点是,事情太“松散”,编译时间不被执行,因为子类程序员只被命令去做某事,而不是真的被迫去做,所以我怀疑这是否被经验丰富的C++程序员认为是好的实践。 有什么好办法还是更好的办法

如果在子类构造函数完成其工作后,只能强制调用超类构造函数。然后超类构造函数可以包含所需的参数


c++不允许这样做:(

听起来你可以使用工厂:

BaseClass {
private:
  Data m_data;
public:
  void setData(const Data& data) { m_data = data; }
  virtual Data generateData() = 0;
};

struct Factory
{
   template<class T>
   static BaseClass* getInstance()
   {
       BaseClass* t = new T;
       t->setData(t->generateData());
       return t;
   }
};
基类{
私人:
数据mu数据;
公众:
void setData(const Data&Data){m_Data=Data;}
虚拟数据生成数据()=0;
};
结构工厂
{
模板
静态基类*getInstance()
{
基类*t=新的t;
t->setData(t->generateData());
返回t;
}
};
并称之为

BaseClass* p = Factory::getInstance<Derived>();
BaseClass*p=Factory::getInstance();
如您所见,非抽象派生类被迫调用
generateData
,因此它们必须生成有效的
数据


我使用原始指针只是为了便于编写,不要:)

听起来你可以使用工厂:

BaseClass {
private:
  Data m_data;
public:
  void setData(const Data& data) { m_data = data; }
  virtual Data generateData() = 0;
};

struct Factory
{
   template<class T>
   static BaseClass* getInstance()
   {
       BaseClass* t = new T;
       t->setData(t->generateData());
       return t;
   }
};
基类{
私人:
数据mu数据;
公众:
void setData(const Data&Data){m_Data=Data;}
虚拟数据生成数据()=0;
};
结构工厂
{
模板
静态基类*getInstance()
{
基类*t=新的t;
t->setData(t->generateData());
返回t;
}
};
并称之为

BaseClass* p = Factory::getInstance<Derived>();
BaseClass*p=Factory::getInstance();
如您所见,非抽象派生类被迫调用
generateData
,因此它们必须生成有效的
数据


我使用原始指针只是为了便于编写,不要:)

而不是一种模式,这是一种反模式。经验法则:受保护的变量不好。继承的行为(通常从具体类继承)是不好的。当然,有时可能有理由忽略这两种情况,但如果你不说你实际上想做什么,很难说清楚。

这不是一种模式,而是一种反模式。经验法则:受保护的变量不好。继承的行为(通常从具体类继承)是不好的。当然,有时可能有理由忽略这两种情况,但如果你不说你实际上想做什么,很难说清楚。

在我看来,不应该使用受保护的变量。我更喜欢使用私有变量和受保护的方法。这样,如果你想使用一个多病态的对象,你可以覆盖你的方法,避免“坏的意外”。如果您的类是
final
,当然您可以直接使用受保护的变量。

在我看来,不应该使用受保护的变量。我更喜欢使用私有变量和受保护的方法。这样,如果你想使用一个多病态的对象,你可以覆盖你的方法,避免“坏的意外”。如果您的类是
final
,当然您可以直接使用受保护的变量。

对我来说,这听起来不太正确。尽管派生类调用基类并非闻所未闻,但更常见的情况是,派生类将重写(virtual)
public\u方法来提供该信息

或者,按照建议,使用工厂功能。或者是一个静态的“构造函数”成员函数,因此不调用new,而是调用一个调用
new
的函数和
特殊函数来设置数据


所有可能的解决办法

对我来说,这听起来不太对。尽管派生类调用基类并非闻所未闻,但更常见的情况是,派生类将重写(virtual)
public\u方法来提供该信息

或者,按照建议,使用工厂功能。或者是一个静态的“构造函数”成员函数,因此不调用new,而是调用一个调用
new
的函数和
特殊函数来设置数据

所有可能的解决办法

如果在子类构造函数完成其工作后,只能强制调用超类构造函数。然后超类构造函数可以包含所需的参数

ctor初始值设定项列表非常强大。虽然只能使用表达式,但这些表达式可以包含函数调用。实际上,可以在构造函数体中执行的任何操作都可以从初始值设定项列表中实现

当然,您必须遵守构造顺序,因此在初始化基类之前不能调用基类上的成员函数。但是您可以在初始化成员时访问基类

class BaseClass
{
  Data m_data;
protected:
  BaseClass( Data&& data ) m_data(data) {}
public:
  Interesting public_method() {
    //returns something interesting about m_data
    //what exactly depends on what the subclass put into m_data
  }
};

class DerivedClass : public BaseClass
{
  static Data make_arg_into_data( const T& arg ) { /* calculate and return the right value for m_data */ }
  static Interesting make_arg_into_member_init( BaseClass* pThis, const T& arg ) { return pThis->public_method(); }
  V m_member;
public:
  DerivedClass( T arg ) BaseClass(make_arg_into_data(arg)), m_member(make_arg_into_member_init(this, arg)) {  }
};
如果在子类构造函数完成其工作后,只能强制调用超类构造函数。然后超类构造函数可以包含所需的参数

ctor初始值设定项列表非常强大。虽然只能使用表达式,但这些表达式可以包含函数调用。实际上,可以在构造函数体中执行的任何操作都可以从初始值设定项列表中实现

当然,您必须遵守构造顺序,因此在初始化基类之前不能调用基类上的成员函数。但是您可以在初始化成员时访问基类

class BaseClass
{
  Data m_data;
protected:
  BaseClass( Data&& data ) m_data(data) {}
public:
  Interesting public_method() {
    //returns something interesting about m_data
    //what exactly depends on what the subclass put into m_data
  }
};

class DerivedClass : public BaseClass
{
  static Data make_arg_into_data( const T& arg ) { /* calculate and return the right value for m_data */ }
  static Interesting make_arg_into_member_init( BaseClass* pThis, const T& arg ) { return pThis->public_method(); }
  V m_member;
public:
  DerivedClass( T arg ) BaseClass(make_arg_into_data(arg)), m_member(make_arg_into_member_init(this, arg)) {  }
};

s/populateData/generateData/??s/populateData/generateData/??在c++@Jay中没有最后一个关键字:在c++03中,从具有私有构造函数和友谊的类的虚拟继承可以实现这一点。在C++11中,实际上有一个
final
关键字<代码>类DerivedClass最终:公共基类{}是的,但是问题是C++的标记,而不是C++ +3。C++中没有最后的关键字:杰伊:C++ 03