【问题标题】:Default constructor with constant members具有常量成员的默认构造函数
【发布时间】:2016-08-08 15:12:58
【问题描述】:

我有一个 C++ 类,比如“客户”,我希望有一个成员作为 ID,

private:
const string x; // Customer's ID

现在普通的构造函数看起来像这样:

Customer::Customer(const string& ID): x(ID){}

现在,我想构建一个默认构造函数,而不初始化 x。可能吗?因为如果我将它初始化为某个随机值,比如说“无标题”,那么我就不能再更改它了,因为它是一个 const。

所以我应该根本不构建一个默认构造函数,还是有可能构建一个不初始化 x 的构造函数,你可以稍后再做?

【问题讨论】:

  • 所有 const 成员必须在构造函数中初始化。你可以做Customer() : x("Some default String") { } 但我不知道这是否是你需要的。如果你以后真的需要修改它,你就不能让它const。另一个危险选项是使用const_cast
  • 需求冲突意味着当前的设计方向不好。您想通过引入默认构造函数来解决什么问题?默认构造函数通常用于声明和稍后更改对象,但您不能有意义地复制分配具有 const 数据成员的类。
  • 如果你想要的是一个“可以稍后修改的 const 成员”,你并不真正想要一个 const 成员。
  • 我在我的 OOP 课程中有一个练习,每个客户都应该有一个 ID,以后不能更改(不像她的手机或地址),所以它会产生很多感觉是 const。此外,我想成为一名“专业人士”,并且我理解手动定义默认 const 是一个好习惯,但这似乎与分配相矛盾。如果确实没有“合法”的方式将默认 ctor 分配给 const 成员,那么我可能不应该定义默认 ctor。
  • 以后不修改,而是以后分配。

标签: c++ class constructor constants


【解决方案1】:

现在,我想构建一个默认构造函数,而不初始化 x。有可能吗?

不,这不可能。

因为如果我将它初始化为某个随机值,比如“无标题”,那么我将无法再更改它,因为它是一个常量。

这正是const 的目的。

所以我应该根本不构建默认构造函数,还是有可能构建一个不初始化 x 的构造函数,您可以稍后再做?

好吧,如果 x 真的应该是 const (我怀疑它实际上是需要的),你不应该提供默认构造函数,除非你可以设法从一些 constexpr 唯一地初始化 x

【讨论】:

  • 谢谢,我需要学习更多 C++ 才能真正理解什么是“专业”编程,什么是真正愚蠢的编程。这个任务的重点是如何成为一个“优秀”的程序员,这就是为什么我在这些事情上浪费了这么多时间。
【解决方案2】:

从技术上讲,您可以稍后对其进行修改(但这可能不是一个好主意)。在您考虑了很长时间之后,请查看以下代码:

const string s = "";
*const_cast<string*>(&s) = "new string";

要在您的代码中使用它,您可以像这样创建一个无参数构造函数:

Customer() : x("") { }

然后在你的代码中修改它:

*const_cast<string*>(&x) = "new string"

虽然这在实践中可能不是一个好主意。您应该查看this post 以了解有关此危险的更多信息

另一种替代方法是创建一个很酷的结构:

template<class T>
class OneTimeAssign{
        T data;
        bool alreadyAssigned;
    public:
        OneTimeAssign() : data(), alreadyAssigned(false){ }
        void operator=(T&& newData){
            if (alreadyAssigned) throw "Error";
            data = newData;
            alreadyAssigned = true;
        }
        operator const T&() const{
            return data;
        }
        const T* const operator->(){
            return &data;
        }
};

然后你可以像这样使用它:

OneTimeAssign<std::string> Mine;
Mine = "First assign";
//Mine = "Second assign"; //Runtime Error
std::cout << (std::string)Mine << std::endl;
system("pause");

【讨论】:

  • const_cast你是认真的吗?
  • 嗯,技术描述是正确的。但正如你提到的那样,这些东西不应该在实践中使用。
  • 这个例子是UB,因为它修改了一个原来的const变量。
  • @Cheersandhth.-Alf 什么是 UB
  • @DarthRubik; UB 是未定义行为的缩写。任何事情都可能发生,包括什么也没有发生,或者崩溃。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-28
  • 1970-01-01
  • 2012-09-01
  • 1970-01-01
  • 2014-04-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多