I wanted the class C inherits from class A its virtual functions, and class D(nested class in class C) inherits from class B(nested class in class A) its data fields, here is what I have.
file1.h
class A{
public:
virtual void foo()=0;
class B{
public:
int data;
};
};
file2.h
class C : public A{
public:
class D : public A::B{
};
};
file2.cpp
void C::foo(){//code}
C::D::D():data(0){//Bad initialization list, error being data is not a member of C::D even it should inherits from its base class
data = 0; //good! compiler can see data is a member of A::B,and C::D inherits from it
}
I got two questions, first one is that is what I am doing the correct way to achieve this kind of inheritance. Secondly, as I commented, why compiler can see data is from A::B in the manual initialization process but not in the initialization list? Shouldn't them be in the same scope? Thank you very much
Edit1:
So if class C::D(foo) doesn't directly inherits from A::B(foo), but C inherits from A, my perception is that since C inherits from A and all its public fields, including its inner class A::B(foo), D(foo) has the exactly same name as A::B(foo) and is an inner class of C, like this, i.e used foo for both inner classes
class A{
public:
class foo{
public:
int data;
};
};
class C : public A{
public:
class foo{
};
};
Would it be confusing for the compiler when I call the C::foo directly? since there are two constructors with the name in the scope? or it chooses to call the "nearest" one, e.g C:foo? instead of climbing up the inheritance chain? Thank you very much
Yes, your approach is the correct way to achieve this kind of inheritance.
Initializer lists are there to control the arguments passed to the constructor. You can pass arguments to B's constructor, but not directly initialize a member of B (it's the job of its constructor). If there is no constructor specified for a base class or a member, the default constructor is used.
In your case, add a constructor to B to achieve what you want.
class A {
public:
class B{
public:
B(int i) : data(i) {}
int data;
};
};
class C : public A {
class D : public A::B {
};
};
C::D::D() :B(0) { }
From a syntactical point of view, it's correct(*1). Apart, of course, from the initialization list. You can only initialize current-class members (not base-class members) in the initializer list. That has nothing to do with the nesting.
class X
{
public:
int x;
};
class Y : X
{
Y() : x(0) {} //still illegal
};
I said syntactical POV because it's a weird thing to do... I'm sure there's a cleaner way to achieve what you actually want.
Your syntax for inheriting from a nested class is correct.
An initializer list is for initializing that class's members; base class members should be initialized in a base class constructor.
Syntactically, the accepted answer has answered your questions very well.
Here's my two cents on the design aspect related to the mechanism:
In your example abstract class A is essentially an interface. An interface should define behavior and behavior only. That being said, I don't think it makes sense to have a nested class in an interface.
1) an interface does not have any data member to be manipulated by the nested class, as is the case with your example. This eliminates the need for a nested class in the first place.
2) a nested class is not a behavior. So it shouldn't appear in an interface.
Now you may argue that your example is just a quick demonstration, and in reality you would have data members for the nested to manipulate, i.e. class A is not a pure interface. You simply want to provide a default implementation for the nested class B and let the class C decides how he wants to customize class B into his own class D. If that's the case I'm afraid the design is even worse.
3) Consider the iterator pattern. Class A is essentially an abstract container that can't be instantiated(because you have a pure virtual function in it) - let's map it to IContainer in our mind. Now you create a class C which has a vector/array implementation, with his own iterator D pointing to some element in the array.
Then you want create another class E which has a hash map implementation, with her own iterator F pointer to some pair in the hash map.
Here's the disaster: very often you cannot have a uniform interface across all the iterator classes(D, F ...) in the implementations of the containing classes(C, E ...) - very likely(consider the assignment operator: BIterator operator=(const BIterator& other);), class D has a function which accepts a class D object as argument: DIterator operator=(const DIterator& other); class F has some function that accepts a class F object as argument: FIterator operator=(const FIterator& other).
On the other hand, this wouldn't work because both DIterator and FIterator are sub-classes of BIterator - You can't override a function with 'narrower'(or 'more specific') arguments as it violates the contravariance of argument types(C++ does not allow contravariant arguments, so it requires matching argument types; so technically you can have FIterator operator=(const BIterator& other) for class F and do a run-time dynamic cast from BIterator to FIterator - but that's ugly and it doesn't make sense: a concrete apple has an assignment operator that assigns an abstract 'fruit' to itself). You just got yourself in a dilemma.
To sum up, due to reasons 1) 2) and 3), don't include a nested class in an interface/abstract base class. The iterator pattern is just an example, there could be numerous occasions on which you shoot yourself in the feet as long as the nested classes interact with the containing classes. If not, then there's no point in having nested classes in the first place.
Related
Consider we have an library that contains a base class, like below,
class Base{
protected:
int a;
public:
Base(int a) : a(a) {}
};
Then, I want to extend it in a new library by adding a new function, like below
class Derived : public Base{
public:
bool is_greater(Derived &y) { return a > y.a; }
};
So that, we can compare their member values using member function is_greater, as
int main(){
Base b1, b2 = // get from the old library's output
Derived d1 = b1, d2 = b2 // convert from base class to derived class
d1.is_greater(d2);
}
So, what's the best solution for this kind of conversion?, performance is the most important point I am concerned about.
Just like any other conversion. You can use a converting constructor:
explicit Derived(const Base& base): Base(base) {}
Conversion operator isn't a practical option in this case since the base doesn't know about the derived type.
Extending a class to add functionality is only viable when either
The class is designed to be extended that way, polymorphic with appropriate APIs, or
You use your extended class everywhere, not the base class.
... otherwise, there is no way to avoid copies or dangerous casts with potential undefined behavior.
Regardless, I'm of the opinion that equating "extension" to "inheritance" is a code smell made popular by abuse of OOP. C++ has free functions. It's un-intrusive and allows you to work with the type and objects you really mean to work with. Furthermore, that protected member is still accessible if you are savvy:
bool is_greater(Base const& l, Base const& r) {
struct fetch : Base { using Base::a; };
return l.*(&fetch::a) > r.*(&fetch::a);
}
We define a local class that inherits from Base, yes. But we don't do it to mess around with objects of the wrong type. All it does is make the member accessible to us. Then we simply use pointer-to-member syntax to access that member on our Base objects in a well-defined manner.
I have a quite niche problem concerning private inheritance. I also have a solution for the problem, but I don't understand why it works.
TL;DR
Why does private inheritance on some intermediate level prevent me from passing the base type as a parameter to a (privately) derived class?
Consider the following code (also available here http://cpp.sh/3p5zv5): I have a composite-type class that can contain pointers to child elements of its own type. Also, that class contains the template method MyMethodTemplate(T value), allowing any type of Parameter. I need to inherit from this class multiple times, such that MyMethodTemplate(T) is not available, and instead only a typed version MyMethod() can be called with e.g. int, string, whatever.
Since the derived classes were going to contain a lot of boilerplate code (not shown here), I wrote the class template cSpecializedComposite that inherits privately from cComposite (successfully hiding MyMethodTemplate()). Its method MyMethod() internally calls MyMethodTemplate() from its parent class. So far, so good.
Now, to get rid of the template parameter in my end user code, I wanted to write trivial classes that publicly inherit from the template (cSpecializedCompositeInt, cSpecializedCompositeString, ...). My assumption was that cSpecializedCompositeInt would know cSpecializedComposite's interface, but not its internals. In cSpecializedCompositeInt's constructor, I can optionally pass a vector of unique_ptr that is passed on to its parent constructor (who does god knows what with it, nothing to see here, move along). Note that the class definition for cComposite is visible to cSpecializedCompositeInt, even if cSpecializedCompositeInt doesn't inherit from it, as far as it knows.
However, I get a compiler error C2247 in cSpecializedCompositeInt's constructor, telling me I can't use cComposite, because cSpecializedComposite inherited privately from it. This occured on both msvc10 and GCC 4.9.2 (the compiler behind http://cpp.sh).
Changing the private inheritance to protected allows cSpecializedCompositeInt to know it inherited indirectly from cComposite, and the compiler error goes away.
In how far is this related to Private Inheritance and Derived Object to Base reference ?
#include <vector>
#include <memory>
class cComposite
{
public:
cComposite(std::vector<std::unique_ptr<cComposite>>&& vecC)
: m_vecC(std::move(vecC))
{
//empty
}
template <typename T>
void MyTemplateMethod(T value)
{
//do something with any type of value
}
private:
std::vector<std::unique_ptr<cComposite>> m_vecC;
};
template <typename MySpecialType>
class cSpecializedComposite : private cComposite
{
public:
cSpecializedComposite(std::vector<std::unique_ptr<cComposite>>&& vecC)
: cComposite(std::move(vecC))
{
//empty
}
void MyMethod(MySpecialType value)
{
//allow only MySpecialType as Input, call base class template method to do something
cComposite::MyTemplateMethod(value);
}
};
class cSpecializedCompositeInt : public cSpecializedComposite<int>
{
public:
cSpecializedCompositeInt(std::vector<std::unique_ptr<cComposite>>&& vecC)
: cSpecializedComposite(std::move(vecC))
{
//empty
}
};
int main(int argc, char* argv[])
{
std::vector<std::unique_ptr<cComposite>> vecC;
cSpecializedCompositeInt spec(std::move(vecC));
spec.MyMethod(5);
return 0;
}
One of the recurring themes on this site is requesting a Minimal, Complete, and Verifiable example. You did do a good job with the "complete" and "verifiable" parts, but not so much with the "minimal". Please allow me to simplify your code to remove potentially distracting details.
// Base class, constructed from a type that involves itself.
class A {
public:
A(A *) {}
};
// Intermediate class, derives privately from the base class.
class B : private A {
public:
B(A * a) : A(a) {}
};
// Most derived class, same constructor parameter as the base class.
class C : public B {
public:
C(A * a) : B(a) {} /// error: 'class A A::A' is inaccessible
};
int main(int argc, char* argv[])
{
return 0;
}
Note the lack of templates and vectors; those are just red herrings. Also, apologies for using raw pointers; they are just a convenient way to introduce the issue with minimal overhead/baggage. (I'd use references, but that would turn one of the constructors into a copy constructor, which feels unwise.)
Look at the definition of B's constructor. In that definition, "A" is used twice: once as part of the type of the parameter, and once in the initializer list. For the latter case, the use of A definitely refers to the (private) base class of the class being constructed. Question: why should the compiler assume that the former case does not also refer to the private base class? (If the private base class was changed, would the parameter's type necessarily change as well? The compiler assumes "yes", but you could introduce another intermediate class, between A and B, which presumably would preserve the parameter's type.)
As far as I know (I have not double-checked the language specs), when you are in the context of B, any mention of its private base class is considered private information. You could think of the constructor's declaration as: B(<private> * a). Since C is not allowed to know the private information of B, it is not allowed to call this constructor. It simply cannot match the parameter list, much the same as if the parameter's type was defined within a private section of B. Fortunately, this can be circumvented by removing a mention of "A" from the parameter list.
In the following, the only change is the introduction and use of a typedef.
class A;
typedef A * special_type;
// Base class, constructed from a type that *indirectly* involves itself.
class A {
public:
A(special_type) {}
};
// Intermediate class, derives privately from the base class.
class B : private A {
public:
B(special_type a) : A(a) {}
};
// Most derived class, same constructor parameter as the base class.
class C : public B {
public:
C(special_type a) : B(a) {} /// no error!
};
int main(int argc, char* argv[])
{
return 0;
}
In your case, this would have the side benefit of introducing a shorter synonym for that rather symbol-rich std::vector<std::unique_ptr<cComposite>>.
I've got following program:
#include<iostream>
using namespace std;
struct Base01{
int m;
Base01():m(2){}
void p(){cout<<m<<endl;}
};
struct Derived01:public Base01{
Derived01():m(3){}
};
struct Derived02:virtual public Base01{
Derived01():m(4){}
};
struct my: Derived01,Derived02{
my():m(5){}
};
int main(){
return 0;
}
Both gcc/clang reports compilation error.
I just wish to know what's the language design consideration here, why derived class can only call base class ctor in initialization list, but cannot use base class members directly?
What you do in the constructor initializer list is initialization. It is something that has to be done only once in the lifetime of the object. In general case, that's what starts the objects lifetime.
Base class's constructor (which finished working before your derived class's constructor-proper became active) has already initialized all direct subobjects of the base class. It has already started their lifetimes. If you attempt to reach-in and initialize a direct subobject of base class from the derived class's constructor, that will obviously be the second initialization of the same object. This is completely unacceptable in C++. The language design generally does not allow you to initialize something the second time.
In your case the subobject in question has fundamental type int, so it is hard to see the harm in such "re-initialization". But consider something less trivial, like an std::string object. How do you suggest the derived class should "undo and redo" the initialization already performed by the base class? And while formally it is possible to do it properly, constructor initializer lists are not intended for that purpose.
In general case doing something like that would require a language feature that would allow user to tell base class's constructor something along the lines of "please, leave this subobject of yours uninitialized, I will reach-in and initialize it later from the derived class". However, C++ does not provide users with such capability. A vaguely similar feature exists in virtual base class initialization, but it serves a very specific (and different) purpose.
The proper way to do this in C++ is to pass that value to the base class constructor. Your Base01 class needs an additional constructor that takes the desired value for m. Something like this:
struct Base01{
int m;
Base01():m(2){}
// Added this:
Base01(int mVal) : m(mVal) {}
void p(){cout<<m<<endl;}
};
struct Derived01:public Base01{
Derived01() : Base01(3) {} // Calling base constructor rather than
// initializing base member
};
struct Derived02:virtual public Base01{
Derived01() : Base01(4){} // Same here
};
struct my: Derived01,Derived02{
my(): Base01(5){} // And here.
};
As AnT said, you can't initialize twice--but you can set it up so that things are initialized the way you want in the first place by doing as above.
You certainly can use a base class member in the ctor-initializer list:
struct Base
{
int x;
Base(int x) : x(x) {}
};
struct Derived
{
int y;
Derived() : Base(7), y(x) {}
}
Here, the base member x appears in the initializer for the derived member y; its value will be used.
AnT has done a very nice job explaining why the ctor-initializer list can't be used to (re-)initialize members of base subobjects.
The fundamental language design considerations in this are separation of concerns (avoiding making a base class depend on its derived classes), and that a base class is responsible for initialising its own members (and any bases it has).
A related consideration is that members of the base class don't exist - as far as the derived class constructor is concerned - before the base class constructor completes. If an initialiser list of a derived class was able to reach in and initialise a base class member, then there are two possible consequences
If the base class constructor has not been invoked, its members will not exist when the derived class tries to initialise them.
If the base class constructor has been invoked, the member has been initialised. Initialisation (as distinct from assignment to reinitialise) happens once in the lifetime of an object, so it does not make sense to initialise it again.
Neither of these possibilities really make sense in practice, unless the base class is poorly designed (e.g. its constructors do not properly initialise its members). The sort of machinery needed so they might make sense (e.g. changing order of construction of base classes in a hierarchy, dependent on what member a derived class is trying to initialise) would make compiler machinery more complicated (e.g. being able to both control and track the order of construction of base class members, in case a derived class should choose to reach in), and also mean that the order of construction of classes would depend on derived classs). This would introduce a dependency of the base class behaviour (the means by which it is initialised) on derived classes.
The simpler means is for the base class to provide a constructor that properly initialised the member in question, and for the derived class constructor to invoke that base class constructor in its initialiser list. All of the above (hypothetical) considerations then go away.
Normally one can change the order in which member initializers run by changing the order in which the members are declared in the class. However, is there a way to get the base class initializer/constructor to not run first?
This is a minimal sketch of my problem:
class SpecialA : public A {
public:
explicit SpecialA(Arg* arg)
: member(expensiveFunction(arg))
, A(member) // <-- This will run first but I don't want it to
{}
private:
T member;
}
No, it is not possible. Class initialization is always like that: base class, members, this class constructor.
The reason for this is simple - since you can reference your members in this class constructor, you have to construct members before you call your constructor. Since you can reference your base class members from your members, you have to have them constructed before this class members.
Is it possible to run member initializers before base-class constructor?
Not as such.
That said, here are a few solutions:
1: move the member to an artificial base:
template<typename T>
class InitializerBase {
protected:
InitializerBase(T&& value) : member(std::move(value)) {}
T member;
};
class SpecialA: public InitializerBase<T>, public A {
public:
SpecialA(Arg *arg) : InitializerBase<T>(expensiveFunction(arg)): A{}
{
}
};
(Probably) the best solution would look like this:
2: use dependency injection for the fully constructed value (this is safest, best design and unless your code has bigger problems, most efficient implementation):
class SpecialA : public A {
public:
explicit SpecialA(T fully_computed_value)
: A(fully_computed_value)
, member(std::move(fully_computed_value)) // no heavy computations performed
{}
private:
T member;
}
Construction:
auto &a = SpecialA(expensiveFunction(arg));
This is the best solution because if expensiveFunction throws, you do not even start constructing the resulting object (the application doesn't have to release the resources for the half-constructed SpecialA).
Edit:That said, if you want to hide the use of the expensive function, the canonical solution to that (canonical because it is reusable, minimalistic and still respects good design) is to add a factory function:
SpecialA make_special(Arg *arg)
{
auto result = expensiveFunction(arg);
// extra steps for creation should go here (validation of the result for example)
return SpecialA( std::move(result) );
}
client code:
auto specialA = make_special(arg); // simplistic to call (almost as simple
// as calling the constructor directly);
// hides the use of the expensive function
// and provides max. reusability (if you
// need to construct a SpecialA without
// calling the expensive function, you
// can (by obtaining the constructor argument
// for SpecialA in a different way)
Just realized how to solve the problem:
class SpecialA : public A {
public:
explicit SpecialA(Arg* arg) : SpecialA(arg, expensiveFunction(arg)) {}
private:
SpecialA(Arg* arg, T&& member) : A(member) , member(member) {};
T member;
}
Base class constructor must be called first.You cannot go any other way around but you can device a way to not make class A base class and call first whatever you want.
The base class is always fully constructed first. There is no way round this.
One alternative would be to break the inheritance and move the the base class to a member variable of the child class.
The order of member initialisation is then the order they appear in the class declaration.
But relying on this can make your code brittle, so do bear that in mind. Putting a suitable comment in the class declaration might not sufficiently discourage an enthusiastic refactorer.
The order of member initializers in the list is irrelevant: the actual
order of initialization is as follows:
1) If the constructor is for
the most-derived class, virtual base classes are initialized in the
order in which they appear in depth-first left-to-right traversal of
the base class declarations (left-to-right refers to the appearance in
base-specifier lists)
2) Then, direct base classes are initialized in
left-to-right order as they appear in this class's base-specifier list
3) Then, non-static data members are initialized in order of
declaration in the class definition.
4) Finally, the body of the
constructor is executed
Source: http://en.cppreference.com/w/cpp/language/initializer_list
in your case it looks like it would be more correct to invert the ownership of the item:
struct A
{
protected:
A(T expensive_object) : _expensive_object(std::move(expensive_object)) {}
protected:
T& access_expensive_object() {
return _expensive_object;
}
private:
T _expensive_object;
};
class SpecialA : public A {
public:
explicit SpecialA(Arg* arg)
: A(expensiveFunction(arg))
{}
void use_object() {
auto& o = expensive_object();
do_something_with(o);
}
};
Also you can use a reserved optional parameter as a placeholder:
class SpecialA : public A {
public:
SpecialA(Arg* arg, std::optional<T> reserved = {}) :
A(reserved = expensiveFunction(arg)),
member(reserved)
{}
private:
T member;
}
It can be better than delegating constructors because it bloats code less when there is a lot of parameters. Also there may be more overhead with delegating constructors (please, correct me if I'm wrong).
Let's say we have:
class Base {...}
class A : public Base {...}
class B : public Base {...}
Is it possible to set as argument type of a generic method:
myMethod([typei'mlookingfor] c) {}
so that I can pass Base, A and B to myMethod() without overloading the method?
and also make it work with references and pointers?
If a pointer or a reference to the base class works for you, just use that:
void myMethod(Base& c) {}
A a;
B b;
myMethod(a); //OK
myMethod(b); //OK
Note that you'll have to use references or pointers to prevent object slicing. If the method is myMethod(Base c), you'll lose type information of derived objects.
If not, you can use a template
template<typename T>
void myMethod(T& c)
{
}
A a;
B b;
myMethod(a);
myMethod(b);
Q: Is it possible to define the type of a method argument to be a class or any derivate class?
A: Sure. Why not?
If you want a "generic" parameter that can be any arbitrary type, just use a template.
Otherwise, if you want "class or any subclass", just use the base class.
Useful quote:
http://wiki.answers.com/Q/What_are_the_concepts_of_object_oriented_programming
Polymorphism allows the programmer to treat derived class members just
like their parent class' members. More precisely, Polymorphism in
object-oriented programming is the ability of objects belonging to
different data types to respond to method calls of methods of the same
name, each one according to an appropriate type-specific behavior.
Which, I believe, is exactly what you're looking for :)
There are 2 ways how to do this. 1st is dynamic polymorphism. Works only with pointers and refs. There is small run time overhead:
void myMethod(Base& x) { ...}
2nd - static polymofism:
template<class T>
std::enable_if<is_base_of<Base,T>::value>
myMethod(base x) {...}