#include<iostream>
using namespace std;
class base
{
protected:
int a;
public:
base(int i)
{
a=i;
}
};
class derived :protected base
{
public:
derived(){}
void show()
{
cout<<a;
}
};
int main()
{
base obj(2);
derived obj1;
obj1.show();
return 0;
}
Why is this program giving error as In constructor derived::derived():
error: no matching function for call to base::base()
Please explain. As i have read in stackoverflow that in case of inheriting as protected, protected members of base class became protected member of derived class. If I am wrong then please share a good link to clear my misconception
Once you define a constructor for any class, the compiler does not generate the default constructor for that class.
You define the parameterized constructor(base(int i)) for base and hence the compiler does not generate the no argument constructor for base.
Resolution:
You will need to define a constructor taking no arguments for base yourself.
Add this to your base class:
base():a(0)
{
}
EDIT:
Is it needed to define default constructor to every class? Or is it necessary to have the constructor that matches the derived type also present in base type?
The answer to both is NO.
The purpose of constructors in C++ is to initialize the member variables of the class inside the constructor. As you understand the compiler generates the default constructor(constructor which takes no arguments) for every class.
But there is a catch, If you yourself define (any)constructor(one with parameters or without) for your class, the compiler does not generate the default constructor for that anymore. The compiler reasoning here is "Huh, this user writes a constrcutor for his class himself, so probably he needs to do something special in the constructor which I cannot do or understand", armed with this reasoning the compiler just does not generate the default no argument constructor anymore.
Your code above and you assume the presence of the default no argument constructor(When derived class object is created). But since you already defined one constructor for your base class the compiler has applied its reasoning and now it refuses to generate any default argument constructor for your base class. Thus the absence of the no argument constructor in the base class results in the compiler error.
You must give a value to the base constructor:
class Derived : protected base
{
public:
Derived() : base(0)
{
}
};
Depending on your implementation, give the value to the base constructor. However, you may want the Derived constructor to take also int as an argument, and then pass it to the base one.
You need to implement an empty constructor in base or invoke the defined base(int) constructor explicitly from derived c-tor. Without it, when derived c'tor is activated,
it is trying to invoke base() [empty c'tor], and it does not exist, and you get your error.
You haven't defined a default constructor for Base..
When you instantiate an instance of Derived, it will call the Derived() constructor, which will in turn try to call the Base() default constructur which doesn't exist as you haven't defined it.
You can either declare an empty constructor for base Base::Base() or call the existing one as below:
#include<iostream>
using namespace std;
class base
{
protected:
int a;
public:
base(int i)
{
a=i;
}
};
class derived :protected base
{
derived(): Base(123) {} --this will call the Base(int i) constructor)
void show()
{
cout<<a;
}
};
int main()
{
base obj(2);
derived obj1;
obj1.show();
return 0;
}
Related
I have following simple code:
#include <iostream>
#include <vector>
template <class Derived>
struct Base
{
Base()
{
static_cast<Derived*>(this)->foo();
}
std::vector<int> m_ints;
};
struct Derived : Base<Derived>
{
Derived() : Base()
{
std::cout << a;
}
void foo()
{
m_ints.push_back(37);
a = 4;
}
int a;
};
int main()
{
Derived d;
return 0;
}
I know about order of calling constructors when object is created. Constructor are called from the "most base -> down". So At the Base constructor Derived object is not fully constructed.
1) Is it safe, to call Derived::foo in Base constructor, when Derived::foo do no touch Derived object? I mean, when there is no such line as a = 4, just touching Base object.
2) If I run posted code, it really works, although I'm touching a which should not exist at that time. Is it guarantee to work? (I tested it on VS2013, VS2010, and GCC 4.8.1 on Ideone)
It will work in this specific case, but I would advise not to do this.
Subtle changes in the code might suddenly break the logic (e.g. someone making the method foo virtual, someone initializing data member a in the constructor or Derived, ...).
If the base class needs information from a derived class, then the derived class must pass that information to the constructor of the base class. In this class, the value 37 should be passed from the constructor of Derived to the constructor of Base.
And when data member a must be initialized, initialize it in the constructor of Derived, not somewhere else.
EDIT: In C++11, if the Derived class wants to inject code in the constructor of Base, it can pass a lambda to Base. Base then simply executes the lambda in its constructor.
such is the code,and with the error:"illegal member initialization: 'a' is not a base or member",what is the meaning of the error info,and why??
class A{
public:
int a;
};
class B:public A{
public:
B();
};
B::B():a(10){ // put "a(10)" into the constructor body is right
}
By the time the constructor of the derived class is invoked, the base class must already be constructed. So it's already too late. To see why it must be this way, consider:
class Base
{
public:
int i;
Base(int q) : i(q) { ; }
};
class Middle : public Base
{
public:
Middle() : Base(2) { printf("i=%d\n", i); }
};
class Derived : public Middle
{
public:
Derived() : i(3) { ; }
}
Now, think about it. The Middle constructor has to run before the Derived constructor. And the Middle constructor ensures that i is 2. So how can the Derived constructor later re-construct it with a different value?
See this answer for a more complete explanation of what's going on here. Basically, you cannot initialise A::a in the initialiser of B, because it is ill-formed according to the standard.
One more important piece of information - remember that if a class does not initialise a member object via the constructor initialization list, then the default constructor for that member will be invoked before that first statement in the base class constructor is executed. When you use the initialiser, what you are actually doing is specifying a constructor to be used INSTEAD of the default constructor.
Clearly when you are constructing a derived class, the parent class member has thus already been constructed, so you cannot reconstruct the base member again, which is what you are trying to do in this example by including it in the derived class initialisation list.
As an aside, if you all you want is to have the derived class be able to set the value of A::a to a specific value, then use the following code instead:
B::B()
{
a = 10;
}
Because the base class may want to initialize things its own way. The proper method is to call on of the base constructors in the initializer list and let the base ctor initialize itself.
basic c++ question i'm fairly sure. if i have a base class with a constructor that takes no parameters, and just initializes some of the protected members, does a derived class instantly call this base constructor too if it matches the parameters (wishful but unlikely thinking), and if not, is there a way to force it to automatically call said base constructor from the derived class WITHOUT having to explicitly tell it to do so in the derived class? I ask because i'm writing a wrapper of sorts and there are some protected members that i want initialized to specific values initially, and then i want to derive and manipulate this base class to my needs, but i wouldn't like an outside user to have to remember to explicitly call the base constructor or set these values within their own constructor.
Yes, the default base constructor is always called unless explicitly stated otherwise.
For example:
class A
{
public:
A() { std::cout << "A"; }
};
class B : A
{
public:
B() {}
};
int main()
{
B b;
return 0;
}
will output:
A
By "explicitly stated otherwise" I mean that you can call a different constructor from the derived class:
class A
{
public:
A() { std::cout << "A"; }
A(int) { std::cout << "AAA"; }
};
class B : A
{
public:
B() : A(1) {} //call A(int)
};
int main()
{
B b;
return 0;
}
will output
AAA
Important if you don't have a default constructor (you declare a non-default constructor and not a default one) or the default constructor is not visible (marked as private), you need to explicitly call an available constructor in the derived class.
If your base-class has a "default constructor" (a constructor that takes no parameters; either explicitly provided by you, or implicitly provided by the compiler because you didn't explicitly provide any constructors), then every derived-class constructor will automatically call that unless you specify that they call a different constructor instead.
(If your base-class doesn't have a "default constructor", because you've provided one or more constructors that take parameters and no constructor that doesn't, then it's a compile-error for a derived-class constructor not to indicate the base-class constructor it calls.)
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.
class A {
A() { }
};
class B : public A {
B() : A() { }
};
Why do we need to call the base class's constructor explicitly inside B's constructor? Isn't it implicit?
It is implicit. You'll need this syntax in case A has a constructor that has arguments, this is the way to pass them.
This is implicit and unnecessary. If you do not call the base class constructor explicitly, the default constructor (the one with no parameters) is used.
There is only a need to call a constructor explicitly if the base class does not have a default constructor, or if you want to call a different one than the default constructor.
The explicit call to the base class constructor can still be added for clarity, but it is not required.
This is only needed in case A's constructor requires extra parameters. In your example, it is not necessary to call the base class' constructor explicitly.
In the case you've shown, it's not necessary. Consider the following:
class A
{
private:
int m_i;
public:
A(int i)
: m_i(i)
{
}
};
class B:public A
{
public:
B()
{
}
};
This won't work (will not compile) because there is no longer a default constructor for A. In this case, you have to explicitly call the base class constructor with the appropriate argument.
The other time you may have to explicitly call a constructor is when the base class has multiple constructors. In this case, you can explicitly call the one that makes sense.