我怎样才能写出干净利落的c++构造函数?

Posted

技术标签:

【中文标题】我怎样才能写出干净利落的c++构造函数?【英文标题】:How could I write c++ construction function clean and clear? 【发布时间】:2020-04-16 03:07:24 【问题描述】:

假设我的班级是这样的:

class Strt 
    public:
        int a0;
        int b0;

        Strt(int a, int b): a(a), b(b) 
        Strt(Strt& s) a = s.a; b = s.b; // these two functions have same contents
        Strt(Strt&& s) a = s.a; b = s.b;
;

问题是左值初始化和右值初始化是相同的,这使得它不干净,因为一旦我想修改类成员变量,我需要以相同的方式修改这两个函数。代码是重复的。我怎样才能把它清理干净以便更好地阅读和维护?

编辑:

有些场合会调用这些构造函数:

Strt func() return Strt(1, 2);
vector<Strt> v;
Strt s(3, 4);
v.push_back(s); // call left construction function
v.emplace_back(func(); // call right construction function

还有一些场合需要修改类,比如我需要在里面添加int c;的新字段:

class Strt 
    public:
        int a0;
        int b0;
        int c0;

        Strt(int a, int b, int c): a(a), b(b), c(c) 
        Strt(Strt& s) a = s.a; b = s.b; c = s.c; // The two functions are duplicatedly modified in the same way
        Strt(Strt&& s) a = s.a; b = s.b; c = s.c;
;

Strt(Strt&amp;)Strt(Strt&amp;&amp;)的内容是否相同,我必须分别修改吗?

【问题讨论】:

您的问题含糊不清。您能否列出构造函数的期望用法及其预期结果?此外,您可能希望将类和属性重命名为更具解释性的命名约定,这是最佳实践。 有用的阅读:The rule of three/five/zero。详细说明何时需要特殊的复制和分配功能以及原因。 【参考方案1】:

由于您的类不拥有任何可移动资源,因此没有理由创建单独的复制和移动构造函数。单个复制构造函数将执行相同的操作:

class Strt 
public:
    int a0;
    int b0;

    Strt(int a, int b): a(a), b(b) 
    Strt(const Strt& s): a(s.a), b(s.b) 
;

Live Demo

当然,因为你的拷贝构造函数除了成员拷贝之外什么都不做,你可以省略它,让编译器为你生成默认的:

class Strt 
public:
    int a0;
    int b0;

    Strt(int a, int b): a(a), b(b) 
;

Live Demo

由于ab 都是公共的,并且您除了从构造函数参数初始化它们之外什么都不做,您可以完全省略您的构造函数并使用聚合初始化:

class Strt 
public:
    int a0;
    int b0;
;

Live Demo

【讨论】:

你好,你好像只用构造对象,那我用()构造呢?我还不需要构造函数吗? 你必须使用统一的初始化语法(使用)来进行聚合初始化。它被称为“统一”是有原因的。其目的是将聚合、数组、对象的初始化语法与用户定义的构造函数统一起来。【参考方案2】:

最干净的解决方案是删除用户声明的构造函数。不需要它们:

class Strt 
    public:
        int a0;
        int b0;
;

【讨论】:

为什么?我还需要删除Strt(int a, int b) 吗? 你不需要。但是如果你这样做,课程会更简单。越简单越好。 是否支持这样的初始化:Strt s(1, 2); 如果我删除它? 否,但它会允许Strt s1, 2;【参考方案3】:

在您的情况下,您可能会默认或省略您的复制/移动构造函数:

class Strt 
public:
    int a0;
    int b0;

    Strt(int a, int b): a(a), b(b) 
    Strt(const Strt&) = default;
    Strt(Strt&&) = default;
;

一般情况下,您可以使用委托constructor:

class Strt 
public:
    int a0;
    int b0;

    Strt(int a, int b): a(a), b(b) 
    Strt(const Strt& rhs) : Strt(rhs.a, rhs.b) 
    Strt(Strt&& rhs) : Strt(rhs) 
;

【讨论】:

以上是关于我怎样才能写出干净利落的c++构造函数?的主要内容,如果未能解决你的问题,请参考以下文章

用C++设计一个不能被继承的类(转)

c ++调用非默认构造函数作为成员[重复]

必须公开聚合字段构造函数才能在 C++ 中使用聚合初始化吗?

c++中的顺序表写法,主要实现(增删查改,构造函数,运算符重载)

有没有办法绕过 C++ 构造函数?

Javascript面向对象编程:非构造函数的继承