I am trying to figure out where I am going wrong with creating variables from a derived class. I have the abstract class, the derived class and am trying to create the derived class as a variable in the main testing program. However I get the error: no matching function for call to DerivedPlayer::DerivedPlayer()’. I haven't been able to find the correct syntax as to create and initialize a variable of the derived class. Also note that the abstract class's constructor is protected.
Abstract Header (Base.h)
#ifndef BASE_H_
#define BASE_H_
#include <iostream>
#include <vector>
class Base {
public:
virtual ~Base() {}
protected:
Base(std::string s) : x(0), s(s), v(0) {}
int x;
std::string s;
std::vector<int> v;
};
#endif
Derived Header (Derived.h)
#ifndef DERIVED_H_
#define DERIVED_H_
#include "Base.h"
class Derived : public Base {
public:
Derived(std::string name){ s = name; }
virtual ~Derived();
};
#endif
Test Code (InTest.cpp)
#include <iostream>
#include "Derived.h"
int main() {
Derived a = Derived("R2-D2");
Derived b = Derived("C-3PO");
return 0;
}
Build Log
03:23:52 **** Incremental Build of configuration Debug for project InTest ****
make all
Building file: ../src/InTest.cpp
Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/InTest.d" -MT"src/InTest.o" -o "src/InTest.o" "../src/InTest.cpp"
In file included from ../src/InTest.cpp:2:0:
../src/Derived.h: In constructor ‘Derived::Derived(std::string)’:
../src/Derived.h:8:27: error: no matching function for call to ‘Base::Base()’
Derived(std::string name){ s = name; }
^
../src/Derived.h:8:27: note: candidates are:
In file included from ../src/Derived.h:4:0,
from ../src/InTest.cpp:2:
../src/Base.h:12:2: note: Base::Base(std::string)
Base(std::string s) : x(0), s(s), v(0) {}
^
../src/Base.h:12:2: note: candidate expects 1 argument, 0 provided
../src/Base.h:7:7: note: Base::Base(const Base&)
class Base {
^
../src/Base.h:7:7: note: candidate expects 1 argument, 0 provided
make: *** [src/InTest.o] Error 1
03:23:52 Build Finished (took 214ms)
Here's the main part of the error message:
../src/Derived.h: In constructor ‘Derived::Derived(std::string)’:
../src/Derived.h:8:27: error: no matching function for call to ‘Base::Base()’
Derived(std::string name){ s = name; }
Because Derived inherits from Base, each time a Derived object is constructed the Base class constructor also have to run. The problem with your current code is that you let the default Base constructor be called, but there isn't any.
You solve it by "calling" the correct Base constructor in the Derived constructor initializer list:
Derived::Derived(std::string name)
: Base(name)
{}
Related
The following code snippets are intentionally made simple only to illustrate the problem. There are two cases I want to show here. The first one in which all code is put in a single file as follows.
#include <iostream>
class Base
{
protected:
double data;
public:
Base(double data);
};
Base::Base(double data = 10) : data{data}{}
class Derived : public Base
{
};
int main()
{
Derived d;
std::cout<<"End of program";
return 0;
}
So far so good. Everything works as expected.
However, if I split the classes into their headers and sources as follows.
Base.hpp
// Base.hpp
#pragma once
class Base
{
protected:
double data;
public:
Base(double data);
};
Base.cpp
// Base.cpp
#include "Base.hpp"
Base::Base(double data = 10) : data{data} {}
Derived.hpp
// Derived.hpp
#pragma once
#include "Base.hpp"
class Derived : public Base
{
};
Derived.cpp
// Derived.cpp
#include "Derived.hpp"
separate.cpp
// separate.cpp
#include "Derived.hpp"
#include <iostream>
int main(){
Derived d;
std::cout<<"End of program";
return 0;
}
I got a lot of build errors as follows.
> Executing task: C/C++: g++.exe build active file <
Starting build...
"C:\mingw32\bin\g++.exe" -g *.cpp -o separate.exe -I F:\StackExchange\Programming\VSCode-Template/cpp
separate.cpp: In function 'int main()':
separate.cpp:5:13: error: use of deleted function 'Derived::Derived()'
Derived d;
^
In file included from separate.cpp:1:
Derived.hpp:4:7: note: 'Derived::Derived()' is implicitly deleted because the default definition would be ill-formed:
class Derived : public Base
^~~~~~~
Derived.hpp:4:7: error: no matching function for call to 'Base::Base()'
In file included from Derived.hpp:2,
from separate.cpp:1:
Base.hpp:8:5: note: candidate: 'Base::Base(double)'
Base(double data);
^~~~
Base.hpp:8:5: note: candidate expects 1 argument, 0 provided
Base.hpp:2:7: note: candidate: 'constexpr Base::Base(const Base&)'
class Base
^~~~
Base.hpp:2:7: note: candidate expects 1 argument, 0 provided
Base.hpp:2:7: note: candidate: 'constexpr Base::Base(Base&&)'
Base.hpp:2:7: note: candidate expects 1 argument, 0 provided
Build finished with error(s).
The terminal process terminated with exit code: -1.
Questions
Could you tell me why this issue happened and how to fix it?
The default argument belongs in the declaration (in the header), not in the definition (in the .cpp file).
Could you tell me why this issue happened
It is because you removed the default argument from the declaration of the constructor. It is no longer a default constructor. The default argument in the definition is only visible in the translation unit containing the definition.
how to fix it?
Move the default arguments of the constructor back to the declaration.
I was trying to implement Shared Objects so before that, I was trying to experiment with that and I got stuck in the following.
#include <iostream>
using namespace std;
class Animal{
public:
virtual void walk(void)=0;
};
class Human : public Animal{
public:
void walk(void){
cout<<"Hi I am a human-being. I have only 2 legs!"<<endl;
}
};
#include <iostream>
using namespace std;
class Animal{
public:
virtual void walk(void)=0;
};
class Tiger : public Animal{
public:
void walk(void){
cout<<"Hi I am a Tiger. I have only 4 legs!"<<endl;
}
};
So these are the 2 child classes in two separate files which I have named as "Tiger.cpp" and "Human.cpp"
and I have compiled them as "g++ -shared -fPIC -o libTiger.so Tiger.cpp" and for the other also.
#include <iostream>
#include "Human.cpp"
#include "Tiger.cpp"
using namespace std;
int main(void){
Animal *aptr; // Declaring a pointer var. of type Animal class
Human hobj; // Declaring an obj. of type Human
Tiger tobj; // Declaring an obj. of type Tiger
aptr = &hobj; // Assigning the addr. of Human object into aptr;
aptr->walk(); // Will call the Human version of walk();
aptr = &tobj;
aptr->walk(); // Will call the Tiger version of walk();
return 0;
}
Now when I tried to build the main() function using g++ it's showing an error as the Animal class is getting defined twice so I understood that and then I tried to move the Parent class into a separate header file and included that in the two-child class and removed from the main file but that's approach is also not working.
The error that is:
++ Animal.cpp -L/home//sugatak99/POC/ -llibrary -o Animal
In file included from Animal.cpp:3:
Tiger.cpp:3:7: error: redefinition of ‘class Animal’
3 | class Animal{
| ^~~~
In file included from Animal.cpp:2:
Human.cpp:3:7: note: previous definition of ‘class Animal’
3 | class Animal{
|
I'm using the ROOT frameowrk and I want to write a class the has a TMultiGraph member. I'm trying to write and assignment operator for my class but I fail due to compilaton issues. The class TMultiGraph keeps it's assignment operator as protected.
The header for my class:
#include "../include/clipper.hpp"
#include "TMultiGraph.h"
#include "TColor.h"
#include "RtypesCore.h"
using namespace ClipperLib;
class ClipperDraw : protected TMultiGraph {
public:
ClipperDraw() {}
ClipperDraw& operator=(const ClipperDraw &c);
private:
TMultiGraph mg;
};
The .cpp is:
ClipperDraw& ClipperDraw::operator=(const ClipperDraw &c)
{
mg = c.mg;
return *this;
}
When compiling I get this message:
g++ -fPIC -Wall `root-config --cflags` -I./include -O2 -c -o obj/ClipperDraw.o src/ClipperDraw.cpp
In file included from src/../include/ClipperDraw.h:12:0,
from src/ClipperDraw.cpp:8:
/home/user/anaconda3/envs/deepjetLinux3/include/TMultiGraph.h: In member function ‘ClipperDraw& ClipperDraw::operator=(const ClipperDraw&)’:
/home/user/anaconda3/envs/deepjetLinux3/include/TMultiGraph.h:47:17: error: ‘TMultiGraph& TMultiGraph::operator=(const TMultiGraph&)’ is protected
TMultiGraph& operator=(const TMultiGraph&);
^
src/ClipperDraw.cpp:26:5: error: within this context
mg = c.mg;
^
Makefile:19: recipe for target 'obj/ClipperDraw.o' failed
make: *** [obj/ClipperDraw.o] Error 1
The copy constructor and the copy assignment operator for TMultiGraph are both marked as protected. That means you cannot assign a TMultiGraph to another TMultiGraph. Inheritance won't help you as it doesn't change that fact.
What inheriting from TMultiGraph will do is allow to to make your own graph class that you can copy. That would look like
class MyMultiGraph : public TMultiGraph {
//...
public:
MyMultiGraph& operator =(const MyMultiGraph& rhs)
{
TMultiGraph::operator=(rhs);
// assign MyMultiGraph member here
}
};
I'm trying to make the following implementation work:
Header of base class:
#ifndef BASE_HH
#define BASE_HH
namespace base {
class Agent
{
public:
int loop () {return loopImpl();}
protected:
virtual int loopImpl() =0;
}
#endif
Header or derived class:
#ifndef DERIVED_HH
#define DERIVED_HH
#include <base/agent.hh>
namespace derived {
class Agent : public base::Agent
{
protected:
virtual int loopImpl();
}
#endif
Source file of derived class:
#include <derived/agent.hh>
int Agent::loopImpl()
{
return 0;
}
Now, when I compile this in the terminal and test it, it works. But when I try compiling an S-function in Matlab that creates an Agent object, i get the following error:
Error using mex
/path/sfunction.cpp In function ‘void mdlStart(SimStruct*)’:
/path/sfunction.cpp:51:56: error: invalid new-expression of abstract class type ‘derived::Agent’
derived::Agent *agent = new derived::Agent ();
/derived_path/agent.hh:28:11: note: because the following virtual functions are pure within ‘derived::Agent’:
class Agent: public base::Agent
In file included from /derived_path/agent.hh:22:0, from /path/sfunction.cpp:13:
/base_path/agent.hh:54:21: note: virtual int base::Agent::loopImpl() virtual int loopImpl () =0;
So it seems the g++4.9 compiler is unable to find the derived member function... Could anybody give me some hints on why this is so and what to do about it? As mentioned above, when I compile a similar file creating an object of the same derived class, it works.
Thank you for your time.
I have next classes:
State.hpp
...
class Engine;
namespace window
{
class State
{ ... } }
WConsole.hpp
...
class Engine;
namespace window
{
class Console: public State
{ .. } }
WMesssage.hpp
...
class Engine;
namespace window
{
class Message: public State
{ ... } }
And all classes link to Engine class:
Engine.hpp
...
namespace window
{
class State;
class Console;
class Message;
}
class Engine
{
...
std::vector< std::unique_ptr<window::State> > m_windowObjects;
std::unique_ptr<window::Console> m_consoleWindow;
std::unique_ptr<window::Message> m_messageWindow;
...
}
And in Engine.cpp I include the headers:
#include "Engine.hpp"
#include "WState.hpp"
#include "WConsole.hpp"
#include "WMessage.hpp"
If I try to compile I get this errors:
In file included from /usr/include/c++/4.8.2/memory:81:0,
from /usr/local/include/SFGUI/Signal.hpp:6,
from /usr/local/include/SFGUI/Object.hpp:4,
from /usr/local/include/SFGUI/Widget.hpp:4,
from /usr/local/include/SFGUI/Container.hpp:4,
from /usr/local/include/SFGUI/Bin.hpp:4,
from /usr/local/include/SFGUI/SFGUI.hpp:6,
from ./include/Handler.hpp:4,
from main.cpp:1:
/usr/include/c++/4.8.2/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = window::Console]':
/usr/include/c++/4.8.2/bits/unique_ptr.h:184:16: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = window::Console; _Dp = std::default_delete<window::Console>]'
./include/Engine.hpp:21:7: required from here
/usr/include/c++/4.8.2/bits/unique_ptr.h:65:22: error: invalid application of 'sizeof' to incomplete type 'window::Console'
static_assert(sizeof(_Tp)>0,
^
/usr/include/c++/4.8.2/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = window::Message]':
/usr/include/c++/4.8.2/bits/unique_ptr.h:184:16: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = window::Message; _Dp = std::default_delete<window::Message>]'
./include/Engine.hpp:21:7: required from here
/usr/include/c++/4.8.2/bits/unique_ptr.h:65:22: error: invalid application of 'sizeof' to incomplete type 'window::Message'
From what I see I don't get an error relating to window::State so mean that I introduced it in the right way, but why I get error relating to window::Console and window::Message?
May affect that classes window::Console and window::Message are derivated from window::State?
I modified to shared_ptr, but including the headers are still a option.
Here is the link for someone who may have same error here
The type argument to unique_ptr must be a complete type for a lot of use cases (see comments for the details); a forward declared class is incomplete. You must have a full definition of the class visible.
Short answer:
explicitly write a destructor of Engine
and move the definition of Engine to the cpp of engine.
Long answer:
Lets see the preprocessing ( all includes are replaced with the content of their header )
and a bit of compiling.
Imagine the following:
//B.h
class A;
class B
{
std::unique_ptr<A> m_A;
public:
B();
};
//B.cpp
#include "B.h"
#include "A.h"
B::B()
: m_A(new A())
{
}
lets see B.i result file after executing the following command (g++ -std=c++11 B.cpp -E B.i):
class A;
class B
{
std::unique_ptr<A> m_A;
public:
B();
};
# 2 "B.cpp" 2
# 1 "A.h" 1
class A
{
public:
int mInt;
explicit A( int aInt = 0 )
: mInt(aInt)
{
}
};
# 3 "B.cpp" 2
B::B()
: m_A(new A())
{
}
Now comes the compiler part. According to cpp reference
If no user-declared prospective (since C++20)destructor is provided for a class type (struct, class, or union), the compiler will always declare a destructor as an inline public member of its class.
lets imagine the file with a declared destructor ( of course there will be declared copy constructor, assignment operator, but lets stick with destructor only )
class A;
class B
{
std::unique_ptr<A> m_A;
public:
B();
~B(){} // <-------- FOCUS HERE
};
# 2 "B.cpp" 2
# 1 "A.h" 1
class A
{
public:
int mInt;
explicit A( int aInt = 0 )
: mInt(aInt)
{
}
};
# 3 "B.cpp" 2
B::B()
: m_A(new A())
{
}
Notice the destructor there, and imagine that thats the place where the destruction of our unique_ptr object or any object will be called.
Realise that in that place our unique_ptr has no idea how to destroy A, since A is only forward declared. A is only defined few lines later, but the compiler can not see that. In order to make it compilable, we must force the destructor definition, to be after the definition of A.
this is simple, create an explicit destructor, and make sure its defined in the cpp file.