Reputation: 143
I have abstract class A
class A{
public:
A(dim) : dim_(dim);
private:
int dim_;
}
and class B
class B : public A{
public:
B(int dim);
}
and I need to make constructor for class B, which works only when dim > 1 and throw assertions otherwise.
in this case
B::B(int dim) : A(dim){
assert(dim > 1);
}
it works, but it's not good solution I think, because instance of the class A was created and deleted.
Than I make init-method for class A:
class A{
public:
void init(int dim){
dim_ = dim;
}
A(int dim){
init(dim);
}
private:
int dim_;
}
and change constructor of class B:
class B : public A {
public:
B(int dim){
assert(dim > 1);
init(dim);
}
}
but it doesn't work. Is there any possible solutions for my problem?
Upvotes: 1
Views: 12243
Reputation: 361402
I think you could write a small myint
class which makes sure that the int
you pass is always greater than 1
:
struct myint
{
int data;
myint(int i) : data(i) { assert(data > 1); }
};
Now use it in your class:
class B : public A{
public:
B(myint dim) //this can still take int, due to implicit conversion!
: A(dim.data) { }
}
Note that you can still construct B
passing int
, as it will implicitly convert into myint
and while the conversion takes place (implicitly), it will test the assert, and if that succeeds, only then you would be able to pass dim.data
to the base class A
. If the assert fails, your program will abort before entering into the base class constructor (without initializing anything in derived class also).
You could even generalize it as:
//Summary : gint<N> makes sure that data > N
template<int N>
struct gint //call it greater int
{
int data;
gint(int i) : data(i) { assert(data > N); } //Use N here!
};
Now use it in your class:
class B : public A{
public:
B(gint<1> dim) //the template argument 1 makes sure that dim.data > 1
: A(dim.data) { }
}
If you need another class, for example:
class Xyz : public A{
public:
B(gint<10> dim) //gint<10> makes sure that dim.data > 10
: A(dim.data) { }
}
Cool, isn't?
Upvotes: 5
Reputation: 70929
If you want to make you second option work, you will have to add an empty constructor to A
. However this will not help you too much because the A
object is created before you enter the constructor for B
, thus whether you have an empty constructor or a consturctor that takes an object of type int, you will always construct an object of type A
.
If A is as simple as you show it in this sample I believe it is not a big deal to constuct it even for invalid dims. If it is more complex I would suggest you create an ampty consturctor for A that initializes as little part of A as possible and then an init
method to do the more complex stuff.
Upvotes: 0