Margareth Reena
Margareth Reena

Reputation: 1430

C++ member variable initialization, but first do some work inside it

I have the following class:

class MyClass {
    public: 
        MyClass(string something);
        ~MyClass();
    private:
        some_namespace::some_class_name my_variable_name;
};

with the following constructor definition:

MyClass::MyClass(string path) {
    string other = "jwrhkfg";
    my_variable_name = some_namespace::some_class_name(path+other)
}

I'm trying to initialize my_variable_name to something dependent on path. I know I could use initializer list:

MyClass::MyClass(string path) : my_variable_name(path+other) {}

But what if I need to do a lot of processing on top of the path string and then initialize my_variable_name? What if I need to do something like this:

MyClass::MyClass(string path) {
    string other = "jwrhkfg";

    if (path="site.com") {
        other = "oritrot";
    } else {
        other = "hsghkr";
    }

    my_variable_name = some_namespace::some_class_name(path+other)
}

I cannot put these ifs in an initializer list.

I thought the code above would work because I only declared the name my_variable_name but didn't define it, so I could do in the constructor, but when I do:

MyClass my_object = MyClass("some_string");

I get that there's no constructor for some_class_name (because the default constructor takes one argument, and here it is trying to initialize even if I didn't initialize it, only declared.

Upvotes: 1

Views: 103

Answers (3)

k.v.
k.v.

Reputation: 1223

Also, if you don't want to create a separate function to be used in intitialization list only, you can use lambdas:

MyClass::MyClass(std::string path)
    : my_variable_name(
        [&]() -> some_namespace::some_class_name
        {
        // do work here and return desired value
            string other = "jwrhkfg";

            if (path="site.com") {
                other = "oritrot";
            } else {
                other = "hsghkr";
            }
            return some_namespace::some_class_name(path+other);
        }() /*call lambda immediately*/ )
{}

Although it's true, that you can use ternary expression is this case (as pointed by user0042), approach with lambda is more generic and can be applicable in case of any complex initialization.

Upvotes: 0

user0042
user0042

Reputation: 8018

I cannot put these ifs in an initialization list.

You can use a function to determine the value and use that in the initialization list:

string MyClass::getOther(string path) {
     if (path == "site.com") {
         return "oritrot";
     }
     return "hsghkr";
}

MyClass::MyClass(string path) : my_variable_name(path + getOther(path)) {
}

Also a ternary conditional would work for your simple case:

MyClass::MyClass(string path) 
: my_variable_name(path + (path == "site.com")?"oritrot":"hsghkr") {
}

Upvotes: 2

SingerOfTheFall
SingerOfTheFall

Reputation: 29966

Make your member a smart pointer instead:

class MyClass {
    public: 
        MyClass(string something);
        ~MyClass();
    private:
        std::unique_ptr<some_namespace::some_class_name> my_variable_name;
};

MyClass:MyClass(string path) {
    string other = "jwrhkfg";
    my_variable_name = std::make_unique<some_namespace::some_class_name>(path+other);
}

Upvotes: 0

Related Questions