I have the following class:
class Base {
public:
Base(string name) {
agg = new Aggregate(name);
}
private:
Aggregate* agg;
};
Now I need to extend this class:
class Derived : Base {
public:
Derived(string name) : Base(name) {
agg2 = new Aggregate2(name);
}
private:
Aggregate2* agg2;
};
What I want is when I create a Base object, Aggregate needs to be created and when I create a Derived object only Aggregate2 should be created.
Now this is not happening because Aggregate its created inside the constructor which is called when I create a Derived object and like this Aggregate and Aggregate2 would be created.
I could move the creation to a different method and call that after creating the object.
Is there any other elegant way to do what I want ?
You may use the following:
class Base {
public:
explicit Base(string name) : agg(new Aggregate(name)) {}
protected:
Base() = default;
private:
std::unique_ptr<Aggregate> agg;
};
class Derived : Base {
public:
// implicit call to Base(), you may be explicit if you want
Derived(string name) : agg2(new Aggregate2(name)) {}
private:
std::unique_ptr<Aggregate2> agg2;
};
This is something you shouldn't do. If your second class isn't supposed to have the first Aggregate member, then the right way is to make two separate classes and not to use inheritance:
class Foo1 { ... };
class Foo2 { ... };
Now if you really have a reason to use inheritance you have a few options:
- Use a base class from which both Foo1 and Foo2 will derive. The base class only contains what is common to both Foo1 and Foo2. The Aggregates you need go separately into Foo1 and Foo2. (recommended)
- Let Foo1 have a union member (if you know the whys and wherefores of unions):
union Bla { std::unique_ptr<Agg1> a1; std::unique_ptr<Agg2> a2; };
And I should strongly emphasize that I can hardly think of an example where the second version is meaningful... Go for a separate base class!
Try this code
class Base {
public:
Base() { }
Base(string name) {
agg = new Aggregate(name);
}
void setName(string name) {
agg = new Aggregate(name);
}
private:
Aggregate* agg;
};
class Derived : Base {
public:
Derived(string name) {
agg2 = new Aggregate2(name);
}
private:
Aggregate2* agg2;
};
You can have a string type data member in Base class; which can be assigned value (same as name,in constructor) and you can access it in derived also(make it protected) to initialize agg2 in Derived class.
I would use a constructor overload for this:
class Base {
public:
Base(string name) : agg(new Aggregate(name)) {}
protected:
Base(Aggregate* agg) : agg(agg) {} //Base will take possession of the passed pointer.
private:
std::unique_ptr<Aggregate> agg;
};
class Derived : Base {
public:
Derived(string name) : Base(new Aggregate2(name)) {}
};
Note:
This assumes that Aggregate2 is derived from Aggregate. This assumption is based on the fact that removing ability of a base class in a derived class is at least a very strong code smell. So I concluded that both aggregates basically serve the same function, so that the second variable to hold the Aggregate2 instance is superfluous, and that Aggregate2 is a subclass of Aggregate to match behavior with relation.
Related
I have the following class hierarchy, where the Base class depends on its derived class to supply it an argument in its constructor:
class Member
{
public:
Member(int v);
};
class Base
{
public:
Base(const Member& m);
};
class Derived : public Base
{
public:
Derived() : m_(123), Base(m_) // <- here is the problem
{
}
private:
Member m_;
};
The problem is, though, that in Derived's constructor, the Base constructor gets called first, when Derived's member variable m_ which it depends on isn't initialized yet.
Is there a way to force the compiler to call the constructor of m_ first or should I just rework my class hierarchy?
You can simulate initializing your member before the base class by making it it's own base class which you initialize first. You can wrap it in a simple class type and have Derived inherit privately from that type before Base. In the following example, Derived has a Member _m; which is initialized and then used to initialize Base.
class Member
{
public:
Member(int) {}
};
class Base
{
public:
Base(const Member&) {}
};
// The new wrapper
struct member_wrapper
{
member_wrapper(int v) : m_(v) {}
Member m_;
};
class Derived : private member_wrapper, public Base
{
public:
Derived() : member_wrapper(123), Base(m_)
{ }
};
Though in this case, since m_ is already a class type and Derived has no other members with that type, you can just inherit privately from Member directly. If you had a non-class type or multiple members of the same type that needed to be initialized before Base you would need to wrap them.
class Member
{
public:
Member(int) {}
};
class Base
{
public:
Base(const Member&) {}
};
class Derived : private Member, public Base
{
public:
Derived() : Member(123), Base(*this)
{ }
};
Instead of this:
class base
{
protected:
base( int value )
: member{value}
{}
int member = 0;
};
class derived_1 : public base
{
public:
derived_1()
: base{ 1 }
{}
};
class derived_2 : public base
{
public:
derived_2()
: base{ 2 }
{}
};
This would be useful:
class base
{
protected:
int member = 0; // Default value
};
class derived_1 : public base
{
base::member = 1; // Instead of passing it to a base class constructor
};
class derived_2 : public base
{
base::member = 2;
};
Will c++1y support this, or similar, syntax?
No, there are currently no plans to allow this. It seems a bit odd to allow an initializer to bypass a base class constructor (if any); it would seem to make more sense to allow a base-class specifier to contain an initializer:
class derived_1 : public base = {1}
{
};
You might consider submitting a proposal, if you can explain how the language would benefit (do you have a concrete use case?).
As a workaround, you might consider using a class template:
template<int I = 0>
class base { protected: int member = I; };
class derived_1: public base<1> {};
If you need to preserve a common base class, use an intermediate base class template:
class base { protected: int member = 0; };
template<int I>
class base_init: public base { base_init() { base::member = I; } };
class derived_1: public base_init<1> {};
Not sure if it's relevant, but the rules on aggregates and aggregate initialization look likely to change in C++14: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3653.html
No and Never.
All fields of base class must be initialized in the constructor in base class. Only the constructor in base class know how its field should be initialized.
You can and must initialize an object or its fields through its constructor.
I have a requirement where I want to initialize a Base class member in derived class.
class SuperBase
{
public:
virtual void Set();
};
class Base:public SuperBase
{
protected:
int *pVal;
public:
void Set()
{
//Some Logic
}
};
class Derived1: public Base
{
public:
// I want to Initialize Base::pVal here and after
// that I want to have this value in Set() of Base.
};
class Derived2: public Base
{
//...Same functionality as Derived1;
//...
};
int main()
{
SuperBase *s = new Derived1;
// Here when I create a Derived1 object automatically,
// the value for pVal will be initialized
s->Set();
//After calling this Set, I want to get the pVal value access in Set.
}
I know that it is an easy thing to do. But these are the things which I cannot use for this problem:
I cannot use Constructor Initializer List for passing values from derived class to Base [I know that I can easily do this through Constructor Initialiser List but there is a requirement where I don't want the existing Class Constructor]
I have tried using CRTP[curiously recurring template pattern], but that is also not suitable as it uses a type of static binding, and in higher view, I have to decide at run time which class object to call Derived1,Derived2.
I also don't want to write any get() in Derived1,Derived2 as I want to only assign values there. This is also a part of my requirement.
I want the Set logic to be only present in Base class and if there is any special case of Set, then I will override Set in Derived classes, otherwise I will access it from Base.
Any Suggestions??? Any Design Patterns??
IMHO, You could do this way:
Option 1 :
a) Override the Set() in Derived1;
b) In Derived1::Set,
-- assign the pVal desired value.
-- Call Base::Set
Sample code:
void Derived::Set(){
pVal = /*some value*/;
Base::Set();
}
Option 2: As pointed by Angew
class Derived1: public Base
{
public:
Derived()
{
pVal = /*some value*/;
}
};
The SuperBase *s = new Derived1; will invoke the above constructor and pVal would be set.
You can only initialise a data member of a class in a member-initialiser-list of that class's constructor. There's no other way. So if you need initialisation, you'll have to add an appropriate constructor to Base and use it (it can be protected, of course).
On the other hand, if it would be enough for your purposes to assign a value into pVal (after it's been initialised by Base's constructor), you can simply do that in the body of the constructor of Derived1 and Derived2:
class Derived1: public Base
{
public:
Derived()
{
pVal = whatever;
}
};
Create constructors for this purpose.
class Base: public SuperBase {
public:
Base() : pVal(0) {} // Default constructor
protected:
int *pVal;
Base(int* Val = 0 /* default value */) : pVal(Val) {} // special constructor
...
};
class Derived1: public Base {
public:
Derived1() : Base(p1 /* Set whatever you want here */) {
}
};
class Derived2: public Base {
public:
Derived2() : Base(p2 /* Set other value here */) {
}
};
You could add another level of inheritance, between the Derived1/Derived2 classes and the Base class, who has a constructor initializing pVal.
Is there a way to provide constructor parameters to a base class when new-ing a derived class instance? (That is, when the base class constructor has default values for these parameters)
E.g.
class Base
{
public:
Base::Base( string name = "" )
: m_name( name ) {};
private
string m_name;
};
class Derived : public Base
{
public:
Derived::Derived() {};
};
Then I need to do something like this:
void main()
{
Base* instance = new Derived( "Jeff" );
};
This obviously doesn't work. Is there a way to new a derived instance and provide a constructor parameter to it's base without having to provide that parameter in the derived class constructor.
Is there a way to new a derived instance and provide a constructor parameter to it's base without having to provide that parameter in the derived class constructor.
No.
Your derived-class constructor needs to take the arguments, and explicitly pass them down to the base-class constructor.
class Derived : public Base
{
public:
Derived::Derived(string name) : Base(name) {};
};
This is the case regardless of whether you're using new or not.
You can't do it if you want distinct names into base class. however distinct name is not a criteria, you can do it using passing constant literals as:
class Base
{
public:
Base::Base( string name = "" )
: m_name( name ) {};
private
string m_name;
};
class Derived : public Base
{
public:
Derived::Derived() : Base ("Jeff") {};
Derived::Derived(string &name) : Base (name) {};
};
OR pass default value to Derived class constructor.
class Derived : public Base
{
public:
Derived::Derived(string name = "Jeff") : Base (name) {};
};
Is this scenario even possible?
class Base
{
int someBaseMemer;
};
template<class T>
class Derived : public T
{
int someNonBaseMemer;
Derived(T* baseInstance);
};
Goal:
Base* pBase = new Base();
pBase->someBaseMemer = 123; // Some value set
Derived<Base>* pDerived = new Derived<Base>(pBase);
The value of pDerived->someBaseMemer should be equeal to pBase->someBaseMember and similar with other base members.
Why would you want to derive and pass the base pointer at the same time? Choose either, nothing stops you from having both. Use inheritance to do the job for you:
class Base
{
public:
Base(int x) : someBaseMemer(x) {}
protected: // at least, otherwise, derived can't access this member
int someBaseMemer;
};
template<class T>
class Derived : public T
{
int someNonBaseMemer;
public:
Derived(int x, int y) : someNonBaseMemer(y), T(x) {}
};
Derived<Base> d(42, 32); // usage
Though not the best of choices as design.
Why wouldn't you actually finish writing and compiling the code?
class Base
{
public: // add this
int someBaseMemer;
};
template<class T>
class Derived : public T
{
public: // add this
int someNonBaseMemer;
Derived(T* baseInstance)
: T(*baseInstance) // add this
{ return; } // add this
};
This compiles and runs as you specified.
EDIT: Or do you mean that someNonBaseMemer should equal someBaseMemer?
Declare someBaseMemr as public or change the declaration from class to struct:
class Base
{
public:
int someBaseMemer;
};
OR
struct Base
{
int someBaseMemr;
};
Remember that a class has private access to all members and methods by default. A struct provides public access by default.
Also, all derived classes should have public inheritance from Base.