【问题标题】:Passing a variable to a constructor in c++在 C++ 中将变量传递给构造函数
【发布时间】:2021-05-15 04:57:18
【问题描述】:

我开始使用 c++ 中的类继承,但我真的陷入了困境。

我试图从子类调用父构造函数并将变量作为参数传递。警告说字段'default_name'在此处使用时未初始化[-Wuninitialized]

class ParentClass {

    public:
        ParentClass(std::string _name): name(_name) {};

        std::string name;

        void printname() {
            std::cout << this->name << std::endl;
        }

}

class DerivedClass: public ParentClass {

    public:

         std::string default_name = "Alex";

         DerivedClass(): ParentClass(default_name) {};

}

这显然不起作用,因为 DerivedClass() 将在 default_name 被初始化之前被调用。有没有办法使用变量从派生类构造父类的对象?

【问题讨论】:

  • static const std::string default_name = "Alex"; 或自 C++20 起static constexpr std::string default_name = "Alex";

标签: c++ class oop variables inheritance


【解决方案1】:

首先构造父类。即使在您的程序中,name 的初始化首先出现,但这并不意味着什么。 C++ 有严格的构造和初始化规则。您正在尝试在 name 初始化之前构造父类。

name 被构造父类被构造之后。

因此,您可以将name 移动到现有父类之前的另一个父类中。那个首先被构造,然后你现有的构造函数将有一个初始化的成员,可以使用..

【讨论】:

  • 谢谢!现在,我是否应该在父类中声明一个 setter 函数并从派生类中调用它以传递 default_name 变量?
  • 由于您将在一个已经构建的对象中调用它,因此初始化和构建规则完全无关,不再重要。
【解决方案2】:

成员总是以相同的顺序初始化:首先是基类子对象,然后是成员在类声明中列出的顺序。因此,您对默认初始化程序的使用或多或少与以下内容相同:

class DerivedClass: public ParentClass {
    public:
         std::string default_name;
         DerivedClass(): ParentClass(default_name),default_name("Alex") {};
}

现在更明显的是default_name在初始化之前被传递给ParentClass的构造函数。我想你已经知道了……要修复它,你有几个选择。由于 default_name 似乎附加到 DerivedClass 而不是类的实例,您可以将其设为静态:

#include <string>
#include <iostream>

class ParentClass {    
    public:
        ParentClass(std::string _name): name(_name) {};    
        std::string name;    
        void printname() {
            std::cout << name;
        }    
};

class DerivedClass: public ParentClass {    
    public:    
         static const std::string default_name;    
         DerivedClass(): ParentClass(default_name) {};    
};

const std::string DerivedClass::default_name = "Alex";

int main(){
    DerivedClass{}.printname();
}

【讨论】:

  • 在这种情况下也可以使用构造函数的默认值,例如DerivedClass(std::string default_name = "Alex")
  • @NotAProgrammer 这是我的第一个想法,但我觉得 OP 也希望在其他地方(默认参数不是)和 "Alex" 不属于 ParentClass(和我没有意识到可以像 Sam 建议的那样在两者之间添加另一个基类,恕我直言,这是最好的解决方案)
  • 公平,如果不知道 OP 特别需要什么,很难说使用什么方法。
【解决方案3】:

必须在当前类成员之前初始化基类,因此会出现错误。在这里,您可以将default_name 设为静态。这样它就可以在对象构建时使用:

class DerivedClass: public ParentClass {

    public:

         static std::string default_name;

         DerivedClass(): ParentClass(default_name) {};

};

std::string DerivedClass::default_name = "Alex";

在这里,default_name 可以(应该?)是const。但实际上,在这里使用文字字符串会更简单:

class DerivedClass: public ParentClass {

    public:

         DerivedClass(): ParentClass("Alex") {};

};

【讨论】:

  • 非常感谢!是的,当然只使用文字字符串会更容易,但我想了解我的错误。
猜你喜欢
  • 2012-01-12
  • 2020-01-16
  • 2016-04-20
  • 2021-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-05
  • 1970-01-01
相关资源
最近更新 更多