From what I understand about inheritance in C++ is that whenever the constructor of a child class is called, constructor of the parent class is called automatically. And as for templated constructors, data type of the template argument is infered automatically i.e. we don't need to specify template arguments separately. The program generates a compilation error which I don't seem to understand.
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
class A{
public:
int x;
int y;
int first(){
return x;
}
int second(){
return y;
}
};
class C{
public:
float a,b;
C(){
a = 0.0f;
b = 0.0f;
}
template<class T>
C(T t){
a = t.first();
b = t.second();
}
};
class D: public C{
public:
float area(){
return a*b;
}
}
int main(){
A a;
a.x = 6;
a.y = 8;
C c(a);
D d(a);
cout<<c.a<<" "<<c.b<<" "<<d.area()<<endl;
}
Compilation error generated
test.cpp: In function ‘int main()’:
test.cpp:56:8: error: no matching function for call to ‘D::D(A&)’
test.cpp:56:8: note: candidates are:
test.cpp:44:7: note: D::D()
test.cpp:44:7: note: candidate expects 0 arguments, 1 provided
test.cpp:44:7: note: D::D(const D&)
test.cpp:44:7: note: no known conversion for argument 1 from ‘A’ to ‘const D&’
I have no idea what is happening here. Any ideas?
D has to pass the constructor argument to C, since you are not using default constructors.
class D : public C {
public:
template <typename T> D (T t) : C(t) {}
float area () { /* ... */ }
};
The reason for the error is that you are trying to construct D with a parameter, but have not declared any constructor that would allow you to do so. Furthermore, you have to pass the parameter into C, otherwise the compiler will use C's default constructor.
The compiler error message can be analyzed like this.
test.cpp:56:8: error: no matching function for call to ‘D::D(A&)’
The compiler is complaining about:
D d(a);
And that it can't figure out how to construct a D when passed something of type A.
It then presents the two choices of constructors it knows about:
test.cpp:44:7: note: D::D()
test.cpp:44:7: note: D::D(const D&)
And it points out that for each one, there is a reason it can't use it. For the first one, it doesn't take any arguments. For the second one, it has no way to convert something of type A into type D.
From what I understand about inheritance in C++ is that whenever the constructor of a child class is called, constructor of the parent class is called automatically.
Careful: The constructor of the parent class is automatically called with the same arguments as the constructor of the child class.
As for the specific problem at hand: There is no constructor declared for class D. You'll get a default constructor and copy constructor as freebies, but not that template-based constructor in class C. Constructors aren't inherited.
Related
In this example:
class MyClass
{
public:
MyClass(int i);
};
template<typename T>
class Base
{
public:
virtual std::unique_ptr<T> createObj()
{
return std::make_unique<T>();
}
};
class Derived : public Base<MyClass>
{
public:
std::unique_ptr<MyClass> createObj() override
{
return std::make_unique<MyClass>(4);
}
};
int main()
{
Derived instance;
auto createdObj = instance.createObj();
}
I cannot call the derived createObj() function. It seems the code is trying to still call the base version with the MyClass instance which leads to compilation failures since the required construction arguments are not passed. Why does this not work as a normal overriden function and call the derived version that does supply the correct arguments?
You misinterpreted the error. The error message is:
In file included from <source>:1:
In file included from /opt/compiler-explorer/gcc-10.3.0/lib/gcc/x86_64-linux-gnu/10.3.0/../../../../include/c++/10.3.0/memory:83:
/opt/compiler-explorer/gcc-10.3.0/lib/gcc/x86_64-linux-gnu/10.3.0/../../../../include/c++/10.3.0/bits/unique_ptr.h:962:34: error: no matching constructor for initialization of 'MyClass'
{ return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
^
<source>:15:21: note: in instantiation of function template specialization 'std::make_unique<MyClass>' requested here
return std::make_unique<T>();
^
<source>:19:7: note: in instantiation of member function 'Base<MyClass>::createObj' requested here
class Derived : public Base<MyClass>
^
<source>:6:5: note: candidate constructor not viable: requires single argument 'i', but no arguments were provided
MyClass(int i);
^
<source>:3:7: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided
class MyClass
^
<source>:3:7: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided
1 error generated.
Base<MyClass> tries to default construct a MyClass but MyClass has no default constuctor. Even if you are not trying to call Base<MyClass>::createObj the method must be valid because it is instantiated as part of Base<MyClass>.
In other words, merely instantiating Base<MyClass> will fail. Not calling the method does not make it less of an error.
I am not entirely sure whats the aim, but if you make the method pure virtual in Base your code compiles without issues:
#include <memory>
class MyClass
{
public:
MyClass(int i) {}
};
template<typename T>
class Base
{
public:
virtual std::unique_ptr<T> createObj() = 0;
};
class Derived : public Base<MyClass>
{
public:
std::unique_ptr<MyClass> createObj() override
{
return std::make_unique<MyClass>(4);
}
};
int main()
{
Derived instance;
auto createdObj = instance.createObj();
}
Alternatively you could provide a default contructor for MyClass.
This question already has answers here:
in constructor, no matching function call to
(2 answers)
Closed 8 years ago.
I have defined a class B, whose constructor accept object of other class(class A) as parameter. Class A constructor also consist of parameter. I am getting error as described below. What is the problem here?
#include<iostream>
using namespace std;
class A{
int val;
A(int val){
this->val=val;
}
};
class B{
A a;
B(A& x){
a=x;
}
};
int main(){
A tempa(3);
B tempb(tempa);
}
Error:
temp.cpp: In constructor ‘B::B(A&)’:
temp.cpp:13:9: error: no matching function for call to ‘A::A()’
temp.cpp:13:9: note: candidates are:
temp.cpp:6:2: note: A::A(int)
temp.cpp:6:2: note: candidate expects 1 argument, 0 provided
temp.cpp:3:7: note: A::A(const A&)
temp.cpp:3:7: note: candidate expects 1 argument, 0 provided
The only way to explicitly initialize a data member is in the constructor initialization list. Once you are in the body of the constructor, the member has been initialized, and all you can do is modify it. In your case, since you are not doing this, the data member would bet implicitly default constructed, but A does not have a default constructor.
You need to use the appropriate constructor in the constructor initialization list:
B(A& x) : a(x)
{
}
Here's the corrected code.
#include<iostream>
using namespace std;
class A{
int val;
public:
A(int val){
this->val=val;
}
};
class B{
A a;
public:
B(A& x):a(x) {
}
};
int main(){
A tempa(3);
B tempb(tempa);
}
Corrections are:
1. Both Constructors of A and B should be public
2. Instead of assignment, let B constructor call A's copy constructor
Consider the following. Class A has a function pointer as a member and accepts a function in its constructor to pass to this member. In a separate file, I have a class B that contains a pointer to class A as a member, and class B also has as a member the function I want to pass to class A.
Below is an example and the errors I receive. What's the standard method of doing something like this?
A.h:
class A {
private:
int (*func)(int);
public:
A(int (*func_)(int));
};
A::A(int (*func_)(int)) : func(func_) {}
B.h:
#include "A.h" // Why can't I forward declare A instead?
class B {
private:
A *A_ptr;
int function(int); // some function
public:
B();
~B();
};
int B::function(int n) {
return n+2; // some return value
}
B::B() {
A_ptr = new A(function);
}
B::~B() {
delete A_ptr;
}
main.cpp:
#include "B.h"
int main() {
B b;
}
Errors I get:
B.h: In constructor ‘B::B()’:
B.h:18:25: error: no matching function for call to ‘A::A(<unresolved overloaded function type>)’
B.h:18:25: note: candidates are:
A.h:9:1: note: A::A(int (*)(int))
A.h:9:1: note: no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘int (*)(int)’
A.h:1:7: note: A::A(const A&)
A.h:1:7: note: no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘const A&’
To answer your question regarding "What's the standard method of doing something like this" I'll assume you mean passing member functions and/or general function pointers around and executing them with some data. Some popular implementations which provide this ability are:
FastDelegate
std::function
boost::function
It really comes down to preference and library choice. Personally, I've used FastDelegate most of the time and then std::function after that.
All the links I posted should have tutorial information to get you up and running and show you how to properly pass and store member functions and/or general function pointers with ease.
Here's an example of using a FastDelegate with your example:
class A
{
public:
// [1] This creates a delegate type. Can used for any function,
// class function, static function, that takes one int
// and has a return type of an int.
typedef FastDelegate1< int, int > Delegate;
// [2] Pass the delegate into 'A' and save a copy of it.
A( const Delegate& delegate ) : _delegate( delegate ) { };
void execute()
{
// [7]
// Result should be 10!
int result = _delegate( 8 );
}
private:
// [3] Storage to save the Delegate in A.
Delegate _delegate;
};
class B
{
public:
B()
{
// [4] Create the delegate
A::Delegate bDelegate;
bDelegate.bind( this, &B::function );
// [5] Create 'A' passing in the delegate.
_aPtr = new A( bDelegate );
// [6] Test it out!! :)
// This causes `A` to execute the Delegate which calls B::function.
_aPtr->execute();
}
~B()
{
delete _aPtr;
}
int function( int n )
{
return n+2;
}
private:
A* _aPtr;
};
I am trying to understand some details of alias-declared classes through C++11's using and how/why this affects a base class constructor call.
Example Code
#include <iostream>
namespace N {
template<typename T>
struct Foo
{
// Foo(){}; // NOTE: If this line is present, error 2 goes away.
Foo(T t):value(t){};
~Foo() = default;
T value;
};
struct BarInt : public Foo<int>
{
BarInt(int t):Foo< int >(t){};
~BarInt() = default;
};
using BarFloat = Foo<float>;
};
struct A : public N::BarInt
{
A(int i=42):BarInt(i){}; //BarInt(i) or N::BarInt(i) doesn't matter here
~A() = default;
};
struct B : public N::BarFloat
{
B(float f=23.0):BarFloat(f){}; //two errors with gcc4.7.2 (with -std=gnu++11)
// B(float f=23.1):N::BarFloat(f){}; //this line seems to work.
~B() = default;
};
int main(int argc, char **argv)
{
A a;
B b;
std::cout << "a's value is "<< a.value << "\n"
<< "b's value is "<< b.value << std::endl;
return 0;
}
gcc 4.7.2 (compiling with -std=gnu++11) generates two errors for this code which I believe to be related (although I do not understand how...)
Error 1
main.cpp: In constructor ‘B::B(float)’:
main.cpp:32:19: error: class ‘B’ does not have any field named ‘BarFloat’
My searches on stackoverflow brought up Is a namespace required when referring to the base class, which mentions injected class name as a starting point for a further search. However, from what I gathered, this explains why I can write the constructor for A the way I did it (i.e. as A(int i=42):BarInt(i){};) and why BarInt(i) does not have to be qualified with the namespace N.
So why doesn't that work with B? According to What is the difference between 'typedef' and 'using' in C++11?, using is the same as a good old typedef, so I guess my question for the first error is how alias-declared class (BarFloat in my example) differ from regular classes (BarInt in my example) in the context of injecting class names. Any pointers are greatly appreciated :)
Error 2
main.cpp:32:29: error: no matching function for call to ‘N::Foo<double>::Foo()’
main.cpp:32:29: note: candidates are:
main.cpp:9:5: note: N::Foo<T>::Foo(T) [with T = double]
main.cpp:9:5: note: candidate expects 1 argument, 0 provided
main.cpp:6:10: note: constexpr N::Foo<double>::Foo(const N::Foo<double>&)
main.cpp:6:10: note: candidate expects 1 argument, 0 provided
This error goes away if I, as already noted in the example code above, introduce an empty Foo() constructor. The question I have, however, is why BarFloat(f) triggers a call to the empty Foo() constructor and, in that case, how BarFloat.value would be possibly set to 23.0.
Post Scriptum
As this is my first post here: Hello stackoverflow and thank you all for the tremendous help you already provided to me through helping others with their problems!
When you inherit from a class, the derived class can access the names of the base class (including the base class name itself) without qualification. You are effectively inheriting the names in the base class. This is why inheriting from N::BarInt allows you to refer to BarInt within A without qualification.
For B, you are inheriting from Foo<double> using the BarFloat alias, but Foo<double> doesn't contain BarFloat, so you don't inherit that name.
The second error is just because of the first failure. Since the compiler didn't see a valid initialization of the base, it is just like you didn't explicitly ininitialize the base at all, so it is forced to initialize it with the default constructor, which you don't have.
class A {
public:
A(int v) {
_val = v;
}
private:
int _val;
};
class B {
public:
B(int v) {
a = A(v); // i think this is the key point
}
private:
A a;
};
int main() {
B b(10);
return 0;
}
compiler says:
test.cpp: In constructor ‘B::B(int)’:
test.cpp:15: error: no matching function for call to ‘A::A()’
test.cpp:5: note: candidates are: A::A(int)
test.cpp:3: note: A::A(const A&)
I've learned Java, and I don't know how to deal with this in C++.
Searching for a couple days, plz tell me can C++ do this?
You need to use a Member Initialization List
B(int v):a(v)
{
}
With:
B(int v)
{
a = A(v); // i think this is the key point
}
a is being assigned a value and not being initialized(which is what you intend), Once the body of an constructor begins {, all its members are already constructed.
Why do you get an error?
The compiler constructs a before constructor body { begins, the compiler uses the no argument constructor of A because you didn't tell it otherwiseNote 1, Since the default no argument constructor is not available hence the error.
Why is the default no argument constructor not generated implicitly?
Once you provide any constructor for your class, the implicitly generated no argument constructor is not generated anymore. You provided overloads for constructor of A and hence there is no implicit generation of the no argument constructor.
Note 1
Using Member Initializer List is the way to tell the compiler to use particular overloaded version of the constructor and not the default no argument constructor.
You have to use initialization lists:
class B {
public:
B(int v) : a(v) { // here
}
private:
A a;
};
Otherwise the compiler will try to construct an A using the default constructor. Since you don't provide one, you get an error.
Yes it can, but you haven't provided a default constructor for A(one that takes no parameters or all parameters have default values), so you can only initialize it in the initializer list:
B(int v) : a(v)
{
}
This is because before the constructor body enters, a will be constructed (or attempted to be constructed) with the default constructor (which isn't available).