I have a question about the way classes using inheritance are constructed. In the example below, the call to the Base constructor is dependent on a function implemented in the Derived class. This function is again dependent on the Derived member generator, which will not be initialized until after the Base constructor call.
If the Base class is constructed first, won't the variable Base::in_ contain garbage data?
class Derived
: public Base
{
Derived()
: Base(get_data()),
generator(5) {}
Generator generator;
int get_data() { return generator.get_some_data(); }
};
class Base
{
Base(int in)
: in_(in) {}
int in_;
}
First, nothing in your code is polymorphic. Polymorphism is about virtual functions.
Next, your class Base depends on nothing. Look between class Base { and the matching }, there's nothing in there that depends on anything outside.
What happens is the construction of the Base subobject within Derived depends on another member of Derived, which is constructed after Base. Your analysis is basically correct, it's a real problem and it needs to be solved by refactoring your classes.
The easiest way is two-stage initialization of Base (the following is pseudocode and probably will not compile):
class Base {
Base(int in = 0) : in_(in) {}
void set(int in) { in_ = in; }
int in_;
};
class Derived : public Base {
Derived() : Base(), generator(5) {
Base::set(generator);
}
...
};
Another method is moving the dependency to another base class:
class Base2 { ... generator implemented here ... };
class Derived : public Base2, public Base {
Derived() : Base2(5), Base(Base2::generator) {}
};
See Order of calling constructors/destructors in inheritance
The constructor for Base will be called before any members of Derived are initialized. So generator will not have been initialized when get_data() is called.
Basically, Base will be initialized with garbage.
I have no idea what the standard says, but this is clearly a matter of what is the value of generator when get_data() is called, as it would be if you call it from somewhere else then the constructor.
Code called from within a constructor is no way different to other code.
My guess is that get_data() is called before generator is constructed and thus you will get a NULL exception at runtime.
Another point to mention is that the base class is of course being constructed first. It is the base class. Derived IS A Base, it has a field in_.
As a rule of thumb it is always a good pattern to:
Avoid method calls from the constructor. Use an additional init method for that.
In any case beware of circular constructor calls.
You also could make get_data abstract in Base and then call it within the Init() of Base which would IMHO be the right way to implement a dependency to child classes as you call it.
class Derived
: public Base
{
Derived()
: Base(),
generator(5) {}
Generator generator;
virtual int get_data() { return generator.get_some_data(); }
};
class Base
{
Base()
{
}
Init() {
in_ = get_data();}
int in_;
virtual int get_data() = 0;
}
Related
When inheritance, do the variables in the base class get copied into the derived class? how the architecture of the child class would be?
{
public:
int m_id;
Base(int id=0)
: m_id(id)
{
}
int getId() const { return m_id; }
};
class Derived: public Base
{
public:
double m_cost;
Derived(double cost=0.0)
: m_cost(cost)
{
}
double getCost() const { return m_cost; }
};
does m_id get copied into derived while derived object's instantiation ?
The derived class (Derived) is not copying the base class (Base) in a strict sense. Derived is inheriting from Base therefore Base is part of Derived. Think of Derived extending Base with new methods and new members.
In your example, Base has a default constructor because the first parameter is an optional parameter (Base(int id=0), you can call the constructor without any arguments to set id to 0).
When you use inheritance, Derived must always call Base's constructor in Derived's constructor before doing anything else (to make sure Base's variables are initialized). However, because Base has a default constructor, the compiler does so magic to make this optional.
If you want to call a specific Base's constructor from Derived's constructor you can do the following:
Derived(double cost=0.0) : Base(1 /* or whatever you want it to be */)
{
m_cost = cost;
}
Is there any point to making virtual member functions, overridden from a base class private, if those are public in the base class?
struct base {
virtual void a();
};
struct derived : base {
// ...
private:
void a() override;
};
If you are forced to do a 2-phase construction on the implementation class (i.e. have an init() method as well as or instead of a constructor that has to be called (I know, but there are reasons), then this stops you calling any /other/ methods directly on the instance pointer before you pass it back as an interface pointer. Go the extra mile, make the inheritance private, and have your one public init function return the interface pointer!
Another reason is you just don't /need/ to write public: in a final implementation class declaration, so then by default everything is private. But why you would do that and use struct instead of class I don't know. Perhaps this was converted from class at some point due to a style war?
Looking at your design, I see one cannot call derived::a directly, but only through a base interface.
Is there any point? Consider that, once we have a derived instance, we can always up-cast to its base, so given
derived d;
while d.a() wouldn't compile, we can always do
base & b = d;
b.a(); //which actually calls derived::a
In other words: derived::a is not that private, after all, and I would discourage this design, which can be confusing to the user.
Things change if the members private in derived are private in base, as well: this time it is clear that they just cannot be called directly, outside base or derived.
Let's say we have a couple of functions, and want them to be called conditionally, according to a value passed as an argument to a third one:
struct base
{
void dosomething(bool x)
{
if(x)
{
do_this();
}
else
{
do_that();
}
}
private:
virtual void do_this(){}
virtual void do_that(){}
};
Thus a derived class could be like:
struct derived : base
{
private:
void do_this() override { }
void do_that() override { }
};
and no other class can call them, unless it extended base itself:
derived d;
d.dosomething(true); //will call do_this() in derived
d.dosomething(false); //will call do_that() in derived
d.do_that() //won't compile
Yes, if you inherit the base class as private. Otherwise, it is more of a weird explicit-like restriction - user has to has to make an explicit conversion to use the function - it is generally ill advised as few will be able to comprehend the author's intention.
If you want to restrict some functions from base class, make a private/protected inheritance and via using keyword declare which base-methods you want to be protected/public in the derived class.
The same reasoning as for non-virtual methods applies: If only the class itself is supposed to call it make it private.
Consider the template method pattern:
struct base {
void foo() { a() ; b(); }
virtual void a() = 0;
virtual void b() = 0;
};
struct derived : base {
private:
void a() override {}
void b() override {}
};
int main()
{
derived().foo();
}
Perhaps a and b should have been protected, but anyhow the derived can change accesibility and it requires some documentation so that derived knows how it is supposed to implement a and b.
In c++ "protected" modifier allow method calls only in derived classes. Is it possible to implement inverse logic - prohibit calling a base class method in the derived classes? The code below illustrates what I want to get.
class Base
{
int data;
protected:
// This constructor should be called only in the derived classes
Base(int d): data(d) { }
public:
// This construcor can be called wherever except a derived classes!
Base(): data(0) { }
};
class Derived : public Base
{
public:
// The developer must not forget to initialize "data"
Derived() : Base(10) {}
// I want to get a compilation error there
Derived() : Base() {}
};
Is it possible to [...] prohibit calling a base class method in the derived classes?
Yes. By using private access specifier. Private names are accessible only to the class itself.
It is not inverse logic however. It is not possible for reduce accessibility of of otherwise public name from derived classes.
// This construcor can be called wherever except a derived classes!
There is no way to do this. A public function can be called by anyone and there is no SFINAE trick you can use to stop it if it is called by a derived class since the constructor has no idea where it is called from.
This seems like a XY problem. Although I do not recommend this (I recommend rethinking the design) I found (for better or worse) a solution inspired from the CRTP pattern:
template <class D = void>
class Base
{
protected:
int data;
protected:
// This constructor should be called only in the derived classes
template <class Der = D, class = std::enable_if_t<std::is_base_of_v<Base, Der>>>
Base(int d): data(d) {}
public:
// This constructor can be called wherever except a derived classes!
template <class Der = D, class = std::enable_if_t<!std::is_base_of_v<Base, Der>>>
Base(): data(0) { }
};
class Derived : public Base<Derived>
{
int mydata = 1;
public:
// The developer must not forget to initialize "data"
Derived() : Base(24) {}
// I want to get a compilation error there
//Derived() : Base() {} // (1) compilation error here
};
auto test()
{
Base b1{};
//Base b2{24}; // (2) compilation error here
Derived d{};
}
Of course there are problems with this. For starters there is nothing stopping from creating a derived class as class Derived : public Base<void>.
And if you want, you can add a common base class
class Base_l0
{
};
template <class D = void>
class Base_l1 : Base_l0
{
};
class Derived : public Base_l1<Derived>
{
};
The short answer is no.
In C++, there is only public protected and private. There is no middle ground. Your functions are either accessible from everywhere (public), from nowhere except the class itself (private), or from the class and its children (protected).
I only want to force the user to perform some additional actions wlile inheritting [sic]. For example, to avoid random errors.
If calling the default constructor causes errors by calling it while inheriting from it, then then it is probable it causes errors when you are not inheriting from it. That means you probably shouldn't have this constructor as public anyway, if at all.
Please look at this code. It just reflects basic concept of what I want to do:
#include <iostream>
using namespace std;
class Base
{
public:
Base()
{
/* Some code I want to reuse */
Redefined();
}
virtual ~Base() {}
void Redefined() { val = 10; }
int val;
};
class Derived : public Base
{
public:
Derived() : Base() {}
~Derived() {}
void Redefined() { val = 25; }
};
int main()
{
Base* check = new Derived();
cout << check->val << endl;
system("pause");
return 0;
}
I want the val property of check object to be 25 instead of 10.
As you can see I have two classes. Base class constructor have some complex functionality, which I want Derived class to have in it's constructor as well. How can I change derived function Redefined so that I won't have to rewrite Derived constructor completely (in fact just copy-pasting the whole base class constructor code and replacing one single line of code - updated version of Redefined function)?
You can't really override a function that way. Normally you could use a virtual functions, but that doesn't work the way you want in the constructor.
A better way is to pass the value you want to the Base constructor:
class Base
{
public:
Base(int init_val = 10)
{
/* Some code I want to reuse */
val = init_val;
}
virtual ~Base() {}
int val;
};
class Derived : public Base
{
public:
Derived() : Base(25) {}
~Derived() {}
};
That way any derived class can pass its choice of value to the base class.
Based on comments above:
I would actually think that the correct solution is to have a "interface" type baseclass (that is, a baseclass with pure virtual functions, and the derived class actually implements the correct behaviour), and then let each class deal with constructing its own DirectX buffers. You may find that you need, say, 2-3 different derived classes that construct buffers in different ways, and then derive from those the classes that actually do the real work. I hope that makes sense.
Alternatively, you would be passing enough parameters to the base-class, such that the buffers can be constructed. But I think the first suggestion is a better choice.
Lately, I have done much programming in Java. There, you call the class you inherited from with super(). (You all probably know that.)
Now I have a class in C++, which has a default constructor which takes some arguments. Example:
class BaseClass {
public:
BaseClass(char *name); ....
If I inherit the class, it gives me the warning that there is no appropriate default constructor available. So, is there something like super() in C++, or do I have to define a function where I initialize all variables?
You do this in the initializer-list of the constructor of the subclass.
class Foo : public BaseClass {
public:
Foo() : BaseClass("asdf") {}
};
Base-class constructors that take arguments have to be called there before any members are initialized.
In the header file define a base class:
class BaseClass {
public:
BaseClass(params);
};
Then define a derived class as inheriting the BaseClass:
class DerivedClass : public BaseClass {
public:
DerivedClass(params);
};
In the source file define the BaseClass constructor:
BaseClass::BaseClass(params)
{
//Perform BaseClass initialization
}
By default the derived constructor only calls the default base constructor with no parameters; so in this example, the base class constructor is NOT called automatically when the derived constructor is called, but it can be achieved simply by adding the base class constructor syntax after a colon (:). Define a derived constructor that automatically calls its base constructor:
DerivedClass::DerivedClass(params) : BaseClass(params)
{
//This occurs AFTER BaseClass(params) is called first and can
//perform additional initialization for the derived class
}
The BaseClass constructor is called BEFORE the DerivedClass constructor, and the same/different parameters params may be forwarded to the base class if desired. This can be nested for deeper derived classes. The derived constructor must call EXACTLY ONE base constructor. The destructors are AUTOMATICALLY called in the REVERSE order that the constructors were called.
EDIT: There is an exception to this rule if you are inheriting from any virtual classes, typically to achieve multiple inheritance or diamond inheritance. Then you MUST explicitly call the base constructors of all virtual base classes and pass the parameters explicitly, otherwise it will only call their default constructors without any parameters. See: virtual inheritance - skipping constructors
You have to use initiailzers:
class DerivedClass : public BaseClass
{
public:
DerivedClass()
: BaseClass(<insert arguments here>)
{
}
};
This is also how you construct members of your class that don't have constructors (or that you want to initialize). Any members not mentioned will be default initialized. For example:
class DerivedClass : public BaseClass
{
public:
DerivedClass()
: BaseClass(<insert arguments here>)
, nc(<insert arguments here>)
//di will be default initialized.
{
}
private:
NeedsConstructor nc;
CanBeDefaultInit di;
};
The order the members are specified in is irrelevant (though the constructors must come first), but the order that they will be constructed in is in declaration order. So nc will always be constructed before di.
Regarding the alternative to super; you'd in most cases use use the base class either in the initialization list of the derived class, or using the Base::someData syntax when you are doing work elsewhere and the derived class redefines data members.
struct Base
{
Base(char* name) { }
virtual ~Base();
int d;
};
struct Derived : Base
{
Derived() : Base("someString") { }
int d;
void foo() { d = Base::d; }
};
Use the name of the base class in an initializer-list. The initializer-list appears after the constructor signature before the method body and can be used to initialize base classes and members.
class Base
{
public:
Base(char* name)
{
// ...
}
};
class Derived : Base
{
public:
Derived()
: Base("hello")
{
// ...
}
};
Or, a pattern used by some people is to define 'super' or 'base' yourself. Perhaps some of the people who favour this technique are Java developers who are moving to C++.
class Derived : Base
{
public:
typedef Base super;
Derived()
: super("hello")
{
// ...
}
};
There is no super() in C++. You have to call the Base Constructor explicitly by name.