【问题标题】:Can I create multiple constructors with the same arguments我可以创建多个具有相同参数的构造函数吗
【发布时间】:2021-11-06 17:25:39
【问题描述】:

我是 C++ 新手,我很想知道您是否可以创建多个具有相同参数的构造函数。比如说我有这个班级,我有病人,我有他们的名字和年龄。我知道我可以像这样创建一个构造函数:

class hospital {
  hospital(){
    setname("John");
    setage(24);
  }
private:
  string name;
  int age;
};

但是我可以像上面那样创建另一个构造函数吗?比如:

hospital patientBilly(){
  setname("Billy");
  setage(32);
}

【问题讨论】:

  • 如何知道调用哪个构造函数?
  • 您可以通过为构造函数提供名称和年龄作为参数来做到这一点。您是否计划为可能存在的每个可能的姓名和年龄组合创建一个构造函数? (而且这种类型可能应该称为“患者”,而不是“医院”。)
  • hospital patientBilly() 不是构造函数,它是一个成员函数,你只能在已经存在的对象上调用它。构造函数没有明确的返回类型,因为它们的名称与类名相同。
  • @Kaldrr:static hospital patientBilly() 方法并非闻所未闻。它有时被称为“命名构造函数模式”。
  • btw name hospital 对于似乎是 Person 的东西来说很奇怪。

标签: c++ class constructor overloading


【解决方案1】:

问题是你重新定义了构造函数。允许只是一种定义。 简化示例:

void myFunc (){};

void myFunc (){};

int
main ()
{
  myFunc ();
}

我应该这样制作医院类:

#include <string>
struct Hospital // struct here to signal we have no invariant. you could also use a class and make the member public
{
  std::string name{}; // no setter and getter if you do not have invariant.
  int age{};
};

int
main ()
{
  auto hospital = Hospital{ .name = "John", .age = 42 }; //c++20 Designated Initializers so we can construct Hospital with a name and age without defining a constructor
}

【讨论】:

    【解决方案2】:

    我相信您目前只是有点困惑。所以让我们把事情整理好……

    一个类描述了对象应该如何表现。构造函数是该描述的一部分,并且等于稍后将创建的所有实例。你理解的第一步应该是:有一个类和它的多个实例/对象。

    因此,您编写一个类并为每个实例/对象提供不同的参数以获取不同的对象。

    例子:

    class hospital {
        public:
        hospital(const std::string& name_, int age_ ):
            name { name_ }, age{ age_ }{
            }
    
        void Print() const
        {   
            std::cout << "Hospital" << name << ":" << age << std::endl;
        }   
    
        private:
        std::string name;
        int age;
    };
    
    int main()
    {
        hospital hospital1{ "John", 24 };
        hospital hospital2{ "Bill", 77 };
    
        hospital1.Print();
        hospital2.Print();
    }
    

    也可以为您以后创建的每个对象创建一个不同的类,但我相信这绝不是您想要做的,尤其是在您的 C++ 职业生涯开始时!

    如果您想创建某种实例列表,您可以将对象存储在容器中并根据需要对容器进行操作。

    int main()
    {
        std::vector< hospital > objs;
    
        objs.emplace_back( "John", 24 );
        objs.emplace_back( "Bill", 77 );
    
        for ( const auto& hos: objs )
        {   
            hos.Print();
        }   
    }
    

    【讨论】:

    • 我知道我可以做到这一点,但我不想每次都在 main 中调用它们。我正在尝试实现一些东西,当我打印时,我会打印整个人员名单,所以在这里,当您调用 print 时,您只调用一个人,而当我想调用 print 时,我想立即给每个人打电话。因此,当我打印医院 2 时,我希望它也打印之前的每个人,就像医院 1 中的每个人一样。
    • 您只需将创建的对象存储在某种容器中...我将扩展我的示例...
    【解决方案3】:

    在您的问题中,您有两个概念,您试图将它们混合在一起。 医院和患者。因此,将它们建模为两个不同的类是有意义的。

    通过这种方式,您可以将患者建模为具有年龄和姓名的事物。 医院是“容纳”病人的东西。

    给患者一个可以传递年龄和姓名的构造器。 并给医院一个或多个增加病人的方法。 在示例中,我展示了如何将患者添加到医院的变体。

    我还对永远不会小于 0 的数字使用无符号变量类型。我在代码中只能使用值且不应更改的地方经常使用 const 关键字。

    #include <iostream>
    #include <string>
    #include <utility>
    #include <vector>
    
    
    //---------------------------------------------------------------------------------------------------------------------
    
    class patient_t
    {
    public:
    
        // You need a constructor like this
        patient_t(const unsigned int age, const std::string& name ) :
            m_age{ age },
            m_name{ name }
        {
        }
    
        // getter function for observing private data
        const unsigned int& age() const noexcept
        {
            return m_age;
        }
    
        // getter function for observing private data
        const std::string& name() const noexcept
        {
            return m_name;
        }
    
    private:
        unsigned int m_age;
        std::string m_name;
    };
    
    // a useful output function to have (will make code later shorter)
    std::ostream& operator<<(std::ostream& os, const patient_t& patient)
    {
        os << "Patient : " << patient.name() << ", age : " << patient.age() << std::endl;
        return os;
    }
    
    //---------------------------------------------------------------------------------------------------------------------
    
    class hospital_t
    {
    public:
        void add_patient(const unsigned int age, const std::string& name)
        {
            m_patients.emplace_back(age,name); // will call patient constructor with two parameters age and name and puts it into vector
        }
    
        void add_patient(const patient_t& patient)
        {
            m_patients.push_back(patient); // store a copy of patient in the vector
        }
    
        const auto& patients() const
        {
            return m_patients;
        }
    
    private:
        std::vector<patient_t> m_patients;
    };
    
    //---------------------------------------------------------------------------------------------------------------------
    
    int main()
    {
        hospital_t hospital;
        patient_t  billy{ 42, "Billy" };
        hospital.add_patient(billy);
        hospital.add_patient(31, "Jane");
    
        for (const auto& patient : hospital.patients())
        {
            std::cout << patient;
        }
    }
    

    【讨论】:

    • 太棒了,这太完美了
    • 对操作员的小修复
    【解决方案4】:

    如果我理解正确,那么你需要定义两个构造函数

    hospital( const std::string &name, int age )
    {
        setname( name );
        setage( age );
    }
    
    hospital() : hospital( "John", 24 )
    {
    }
    

    然后你就可以写声明一个类的对象了

    hospital patientBilly( "Billy", 32 );
    

    【讨论】:

    • 好的,我想我明白您使用构造函数作为构造函数对吧?
    • 不,我不想声明多个对象
    • @ConnerSmith 您需要定义一个具有指定名称和年龄的类的对象。所以你需要一个接受两个参数的对应构造函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多