Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;:在继承链中的何处放置构造函数?_C++_Inheritance_Constructor - Fatal编程技术网

C++ C++;:在继承链中的何处放置构造函数?

C++ C++;:在继承链中的何处放置构造函数?,c++,inheritance,constructor,C++,Inheritance,Constructor,我面临以下困境: 我有一个完整的抽象类。每个继承类将需要3个相同的参数。它们中的每一个还需要其他特定参数 我可以: 1) 实现一个公共构造函数来初始化我的基类中的3个公共参数,但是我必须为相应的字段生成非抽象的getter(它们是私有的) 或 2) 让我的基类保持抽象,并在继承的类中实现构造函数,但是我必须在每个类字段中为公共参数设置构造函数 哪种方法更好?我不想使用受保护的成员 抽象类是指至少有一个纯虚函数(或者,你称之为抽象函数)的类。拥有非抽象、非虚函数不会改变这样一个事实:只要类至少有一

我面临以下困境:

我有一个完整的抽象类。每个继承类将需要3个相同的参数。它们中的每一个还需要其他特定参数

我可以:

1) 实现一个公共构造函数来初始化我的基类中的3个公共参数,但是我必须为相应的字段生成非抽象的getter(它们是私有的)

2) 让我的基类保持抽象,并在继承的类中实现构造函数,但是我必须在每个类字段中为公共参数设置构造函数


哪种方法更好?我不想使用受保护的成员

抽象类是指至少有一个纯虚函数(或者,你称之为抽象函数)的类。拥有非抽象、非虚函数不会改变这样一个事实:只要类至少有一个纯虚函数,它就是抽象的。在基类中使用公共功能,即使它是抽象的。

抽象类是指至少有一个纯虚函数(或者,你称之为抽象函数)的类。拥有非抽象、非虚函数不会改变这样一个事实:只要类至少有一个纯虚函数,它就是抽象的。尽量在基类中使用通用功能,即使它是抽象的。

如果您的类看起来像这样,则为纯抽象类:

class IFoo {
   public:
    virtual void doThings() = 0;
}

class Foo {
   public:
      Foo(std::string str);
     void doThings() override;
}
您的继承的价值在于为您提供了在运行时用另一个替代Foo的机会,但将具体实现隐藏在接口后面。你不能把这个优势用在构造函数上,因为没有虚拟构造函数(这就是为什么像虚拟构造函数这样的东西是存在的)。所有
Foo
的实现都使用
std::string
,所有
doThings
的实现都使用该字符串?很好,但这是巧合,不是合同,也不属于
IFoo

让我们来讨论一下您是否在
IFoo
中创建了具体的实现,从而使其成为一个抽象类而不是一个纯抽象类(
IFoo
,顺便说一句,这将是一个坏名字)(*1)让我们假设使用继承来共享行为是类的正确选择,这有时是正确的。如果类中有需要初始化的字段,请创建一个
受保护的
构造函数(从每个子实现调用),并删除/ommit默认构造函数

class BaseFoo {
       private:
         std::string _fooo;
       protected:
         BaseFoo(std::string fooo) : _fooo(fooo) {}
       public:
         virtual void doThings() = 0;
         std::string whatsTheBaseString() { return _fooo;}
   }
上面是正确地从子构造函数传递基类所需字段的方法。这是一种编译时保证,子类将“记住”正确初始化
\u fooo
,并避免将实际成员
fooo
暴露给子类。试图在所有子构造函数中直接初始化
\u fooo
,在这里是不正确的


*1)为什么这么快

如果您的类看起来像这样,则为纯抽象类:

class IFoo {
   public:
    virtual void doThings() = 0;
}

class Foo {
   public:
      Foo(std::string str);
     void doThings() override;
}
您的继承的价值在于为您提供了在运行时用另一个替代Foo的机会,但将具体实现隐藏在接口后面。你不能把这个优势用在构造函数上,因为没有虚拟构造函数(这就是为什么像虚拟构造函数这样的东西是存在的)。所有
Foo
的实现都使用
std::string
,所有
doThings
的实现都使用该字符串?很好,但这是巧合,不是合同,也不属于
IFoo

让我们来讨论一下您是否在
IFoo
中创建了具体的实现,从而使其成为一个抽象类而不是一个纯抽象类(
IFoo
,顺便说一句,这将是一个坏名字)(*1)让我们假设使用继承来共享行为是类的正确选择,这有时是正确的。如果类中有需要初始化的字段,请创建一个
受保护的
构造函数(从每个子实现调用),并删除/ommit默认构造函数

class BaseFoo {
       private:
         std::string _fooo;
       protected:
         BaseFoo(std::string fooo) : _fooo(fooo) {}
       public:
         virtual void doThings() = 0;
         std::string whatsTheBaseString() { return _fooo;}
   }
上面是正确地从子构造函数传递基类所需字段的方法。这是一种编译时保证,子类将“记住”正确初始化
\u fooo
,并避免将实际成员
fooo
暴露给子类。试图在所有子构造函数中直接初始化
\u fooo
,在这里是不正确的


*1)为什么这么快

避免代码重复而又不污染与数据成员的抽象接口的一种方法是引入额外的继承级别:

// Only pure virtual functions here
class Interface {
public:
    virtual void foo() = 0;
};

// Things shared between implementations
class AbstractBase : public Interface {

};

class ImplementationA : public AbstractBase {
};

class ImplementationB : public AbstractBase {
};

避免代码重复而又不污染与数据成员的抽象接口的一种方法是引入额外的继承级别:

// Only pure virtual functions here
class Interface {
public:
    virtual void foo() = 0;
};

// Things shared between implementations
class AbstractBase : public Interface {

};

class ImplementationA : public AbstractBase {
};

class ImplementationB : public AbstractBase {
};

我不知道构造函数参数与类成员的getter有什么关系。要么你不需要获得者,要么你需要。我看不出这与类中的各种构造函数有什么关系。您可能要寻找的是委托构造函数。但是,如果我在基类中将字段作为private放置,则每个派生类都需要访问基类的private memeber,其中存储有公共参数。因此需要getter的后代。这就是受保护继承的目的。我不知道构造函数参数与类成员的getter有什么关系。要么你不需要获得者,要么你需要。我看不出这与类中的各种构造函数有什么关系。您可能要寻找的是委托构造函数。但是,如果我在基类中将字段作为private放置,则每个派生类都需要访问基类的private memeber,其中存储有公共参数。因此需要后代getter。这就是受保护继承的用途。取决于继承的类型,私有继承可以实现使用关系,私有基类很可能有数据成员。我想这个答案正是我想知道的。谢谢你。@ErikAla