4

I have a class in C++, say "Customer", and I want to have a member of it for ID,

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

now the normal constructor would look like this:

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

Now, I want to build a default constructor, without initializing x. Is it possible? Because if I initialize it to some random value, say "untitled" then I can't change it anymore because its a const.

So should I not build a default constructor at all, or is there a possibility of building one that doesn't initialize x and you can do that later?

Ulrich Eckhardt
  • 16,572
  • 3
  • 28
  • 55
michael kova
  • 105
  • 2
  • 8
  • All const members must be intialized in the constructor. You could do `Customer() : x("Some default String") { }` but I don't know if that is what you need. If you really need to modify it at a later time you could just not make it `const`. Another **dangerous** option is to use `const_cast` – DarthRubik Apr 16 '16 at 17:53
  • 1
    The conflicting requirements mean that the current design direction is ungood. What problem are you trying to solve by introducing a default constructor? A default constructor is often used to declare and later change an object, but you can't meaningfully copy assign a class with a `const` data member. – Cheers and hth. - Alf Apr 16 '16 at 17:53
  • If what you want is a "const member that can maybe be modified later" you don't really want a const member. – molbdnilo Apr 16 '16 at 17:55
  • I have an exercise in my course on OOP and for every customer there should be an ID, which you can not change at a later time (unlike her cellphone or address), so it makes a lot of sense to be const. Also I want to be a "professional" doing this and I understood defining manually a default const is a good habit, but it seems to contradict the assignment. If there is indeed no "legitimate" way to assign a default ctor to const members then probably I should not define a default ctor. – michael kova Apr 16 '16 at 17:59
  • Not modified later, but rather assigned later. – michael kova Apr 16 '16 at 17:59

2 Answers2

3

Now, I want to build a default constructor, without initializing x. Is it possible?

No, it's not possible.

Because if I initialize it to some random value, say "untitled" then I can't change it anymore because its a const.

That's exactly the purpose of const.

So should I not build a default constructor at all, or is there a possibility of building one that doesn't initialize x and you can do that later?

Well, if x really should be const (which I doubt is actually needed), you shouldn't provide a default constructor, unless you could manage to initialize x uniquely from some constexpr.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • 1
    Thank you, I need to learn more C++ to really understand what is kind of "professional" programming and what is really idiotic programming. The whole point of this assignment is how to be a "good" programmer and that's why I waste so much time on these things. – michael kova Apr 16 '16 at 18:19
0

Technically you can modify it later (but that is probably not a good idea). After you have thought about it for a good long time look at this code:

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

To use this in your code you could create a parameterless constructor like this:

Customer() : x("") { }

And then modify it later in your code:

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

Although this might be a bad idea to do in practice. You should look at this post for more info about the dangers of this

Another alternative to this is to create a cool struct:

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;
        }
};

You could then use it like this:

OneTimeAssign<std::string> Mine;
Mine = "First assign";
//Mine = "Second assign"; //Runtime Error
std::cout << (std::string)Mine << std::endl;
system("pause");
Community
  • 1
  • 1
DarthRubik
  • 3,927
  • 1
  • 18
  • 54