Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I´ve browsed other similar topics and did not find an answer to my problem...
The code below illustrates the situation. A Base class and a Derived class:
Base.hpp
namespace test {
template<class T>
class Base {
public:
Base();
virtual ~Base();
};
}
Base.cpp
#include "Base.hpp"
namespace test {
template<class T>
Base<T>::Base() {
// TODO Auto-generated constructor stub
};
template<class T>
Base<T>::~Base() {
// TODO Auto-generated destructor stub
};
}
Derived.hpp
namespace test {
class Derived : public Base<int> {
public:
Derived();
virtual ~Derived();
};
} /* namespace aeirtuaccess */
Derived.cpp
#include "Derived.hpp"
namespace test {
Derived::Derived() {
// TODO Auto-generated constructor stub
};
Derived::~Derived() {
// TODO Auto-generated destructor stub
};
}
When I compile this code with Coliru - see it in action here, it works fine, but when I go to my Ubuntu environment using g++ I´m having the following error:
>g++ Base.cpp Derived.cppIn file included from Derived.cpp:2:0:
Derived.hpp:3:28: error: expected template-name before ‘<’ token
class Derived : public Base<int> {
^
Derived.hpp:3:28: error: expected ‘{’ before ‘<’ token
Derived.hpp:3:28: error: expected unqualified-id before ‘<’ token
Derived.cpp:6:18: error: invalid use of incomplete type ‘class test::Derived’
Derived::Derived() {
^
In file included from Derived.cpp:2:0:
Derived.hpp:3:7: error: forward declaration of ‘class test::Derived’
class Derived : public Base<int> {
^
Derived.cpp:11:19: error: invalid use of incomplete type ‘class test::Derived’
Derived::~Derived() {
^
In file included from Derived.cpp:2:0:
Derived.hpp:3:7: error: forward declaration of ‘class test::Derived’
class Derived : public Base<int> {
Is there any difference between the compilers ? Should I use a specific g++ flag or version ? Is there something else that I need to do to fix that in my Ubuntu environment ?
In Derived.hpp, you need to add:
#include "Base.hpp"
at the top. Otherwise, the compiler doesn't know what Base refers to when compiling this file.
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 have a class RenderMachine which includes RenderObject and vice versa. I know there have been tons of questions about this error, but the solution for this doesn't do anything.
They say the error is mostly because a include-loop but I don't have one because in the RenderObject header I only allocate memory for a pointer to RenderMachine and vice versa.
RenderObject.h
#pragma once
#include "RenderMachine.h"
class RenderObject
{
public:
RenderObject(RenderMachine* rm){}
};
RenderMachine.h
#pragma once
#include "RenderObject.h"
class RenderMachine
{
public:
void add(RenderObject* renderObject);
};
The exact error is
error: expected ‘)’ before ‘*’ token
RenderObject(RenderMachine* rm)
^
Edit:
#include "RenderMachine.h"
class RenderMachine;
class RenderObject : public sf::Drawable
{
private:
int renderId;
public:
RenderObject(RenderMachine* rm){ (*rm).add(*this); }
int getRenderId() const { return renderId; }
#include "RenderObject.h"
class RenderMachine
{
std::vector< std::vector<sf::Drawable*> > renderVector;
public:
void add(RenderObject* renderObject);
And RenderMachine.cpp
#include "RenderMachine.h"
void RenderMachine::add(RenderObject* renderObject)
{
renderVector[(*renderObject).getRenderId()].push_back(renderObject);
}
Your call to add in the constructor of RenderObject should be done when RenderMachine is known (when it's a complete type). This goes for all calls to an object of the other type that you now have in your header files. Like this:
// RenderObject.h
class RenderMachine;
class RenderObject {
public:
RenderObject(RenderMachine* rm);
};
// RenderMachine.h
class RenderObject;
class RenderMachine {
public:
void add(RenderObject* renderObject);
};
// RenderObject.cpp
RenderObject::RenderObject(RenderMachine* rm) {
rm->add(this);
}
// RenderMachine.cpp
void RenderMachine::add(RenderObject* ro) {
}
You have a classic chicken-and-egg problem. The compiler cannot parse one header without first parsing the other header, because the classes in the headers refer to each other.
The solution is to use a forward declaration like this:
#include "RenderMachine.h"
class RenderMachine; // forward declaration
class RenderObject
{
public:
RenderObject(RenderMachine* rm){}
};
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)
{}
I have some c++ code that will compile fine in Visual Studio 2013 but will not compile in linux using g++ (no IDE).
What is causing the difference and how can I make the code compile on linux? Is it because they are different compilers? Do I need a specific compiler setting?
Code:
#include <iostream>
typedef class IApp;
typedef class Component;
class Component
{
public:
protected:
IApp* app;
template<typename T>
void registerEvent()
{
app->logEvent();
}
};
class IApp : protected Component
{
public:
static IApp NULL_APP;
void logEvent()
{
printf("Event Logged\n");
}
protected:
virtual void foo() = 0;
};
int main(int argc, char** argv)
{
printf("Alive\n");
system("pause");
return 0;
}
On windows I get no compiler errors. On linux I get the following compiler errors:
g++ - o res main.cpp - std = c++11
main.cpp:3 : 15 : warning : ‘typedef’ was ignored in this declaration[enabled by default]
typedef class IApp;
^
main.cpp:4 : 15 : warning : ‘typedef’ was ignored in this declaration[enabled by default]
typedef class Component;
^
main.cpp: In member function ‘void Component::registerEvent()’ :
main.cpp : 16 : 6 : error : invalid use of incomplete type ‘class IApp’
app->logEvent();
^
main.cpp:3 : 15 : error : forward declaration of ‘class IApp’
typedef class IApp;
^
main.cpp: At global scope :
main.cpp : 23 : 14 : error : cannot declare variable ‘IApp::NULL_APP’ to be of abstract type ‘IApp’
static IApp NULL_APP;
^
main.cpp:20 : 7 : note : because the following virtual functions are pure within ‘IApp’ :
class IApp : protected Component
^
main.cpp : 31 : 15 : note : virtual void IApp::foo()
virtual void foo() = 0;
^
make: ***[all] Error 1
Here you should simply remove typedef:
typedef class IApp;
Then this template method should be defined out-of-line, below IApp:
template<typename T>
void registerEvent()
{
app->logEvent();
}
Otherwise, it doesn't see the declaration of IApp which it needs to dereference.
Finally, this does not make sense:
virtual void foo() = 0;
Because the same class has a static member of its own class type, so needs to instantiate it. But you've prevented that with a pure virtual function.
GCC is right not to compile this code.
Leave out the typedef keywords before the forward class declarations, they're not necessary. Just class MyClass; is sufficient for a forward declaration. The other issue is that foo() is pure virtual - you need to implement it if you want to instantiate the class. I'm surprised the Microsoft complier doesn't complain but then that's Microsoft.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Error calling template method in “templated-base-class”
The following code compiles with MSVC10 but not with gcc 4.2.1:
template<class BaseQNativeWindow>
class NativeWindow : public BaseQNativeWindow
{
public:
NativeWindow(AIPanelPlatformWindow handle) : BaseQNativeWindow(handle)
{}
protected:
virtual void closeEvent(QCloseEvent *e)
{
QList<QWidget *> childrenList;
childrenList = BaseQNativeWindow::findChildren< QWidget * >(); // GCC ERROR
foreach(QWidget *child, childrenList)
{
child->close();
}
}
};
This is what gcc complains about:
error: expected primary-expression before ‘*’ token
error: expected primary-expression before ‘>’ token
error: expected primary-expression before ‘)’ token
findChildren is a templated method that BaseQNativeWindow must provide. It seems that gcc assumes that findChildren is not a template even before knowing what type BaseQNativeWiindow is. Can anyone explain this?
Thanks.
You have to say:
BaseQNativeWindow::template findChildren< QWidget * >()
// ^^^^^^^^
Since findChildren is a dependent name, its meaning must be disambiguated.