Sebastian Hoffmann
Sebastian Hoffmann

Reputation: 11502

Execute checks before initialization list

I have a member of class A in my own class which constructor takes multiple parameters. Im forwarding parameters of my own class to the constructor of class A. But its important that these parameters are correct, so i need to check them before consructing the member of A. And heres the problem: I could leave out the member in the member intialization list, effectively calling the default constructor. After the checks in the constructor i could then call A`s constructor in a assigment. Although, this produces a error since the destructor of A is private.

How do i solve this?

MyClass::MyClass(int someParam) : otherMember(2){
//checks for someParam
member = A(someParam); // <- produces error
}

Upvotes: 8

Views: 1618

Answers (3)

Caduchon
Caduchon

Reputation: 5231

Another way to check before the construction is to make the constructor private and check before calling it:

# include <cassert>

class Foo
{
    private:
        int x;
        int y;
    public:
        Foo(int x_, int y_);
    private:
        struct InitCheckDone {};
        Foo(InitCheckDone, int x_, int y_);
};

Foo::Foo(int x_, int y_) : Foo((
    assert(x_ >= 1),
    assert(y_ >= 1),
    assert(x_ + y_ <= 20),
    InitCheckDone()), x_, y_) {}

Foo::Foo(InitCheckDone, int x_, int y_) :
    x(x_),
    y(y_)
{}

int main()
{
    Foo f1(3,3);
    Foo f2(12,17);
    return 0;
}

Upvotes: 0

escargot agile
escargot agile

Reputation: 22389

I see two ways of approaching this:

  1. Make sure class A can be used with a parameter-less constructor, and set someParam in a separate method: A.SetSomeParam(someParam)

  2. Not inherit from A, but rather hold a member object of type A, and then you can construct it whenever you like.

Upvotes: 0

bdonlan
bdonlan

Reputation: 231343

You're going to need an accessible destructor no matter what you do. But to address your question, one option would be to call a static function to check parameters from within the initializer:

class MyClass {
  private:
    static void checkParam(int);
// ...
};

MyClass::MyClass(int someParam) : otherMember( (checkParam(someParam), 2) ) {
  // ...
}

static void MyClass::checkParam(int someParam) {
  if (...) throw someException();
}

Note that the , used there is the comma operator, not an argument separator - it evaluates both left and right expressions, and throws away the result of the left.

Upvotes: 11

Related Questions