I have the following classes ( Enemy class is the parent class and Boss and SuperDuperBoss are children classes). My problem with SuperDuperBoss
#ifndef _ENEMY_H
#define _ENEMY_H
#include <iostream>
class Enemy
{
public:
void SelectAnimation();
inline void runAI()
{
std::cout << "RunAI() is running ...\n";
}
private:
int m_iHiPoints;
};
#endif
and this is the children classes
#ifndef BOSS_H
#define BOSS_H
#include "Enemy.h"
class Boss : public Enemy
{
public:
void runAI();
};
class SuperDuperBoss : public Boss
{
public:
void runAI();
};
#endif
This is the main.cpp
#include "Enemy.h"
#include "Boss.h"
int main()
{
Enemy enemy1;
Boss boss1;
SuperDuperBoss supBoss;
enemy1.runAI();
boss1.runAI();
supBoss.runAI(); // <--- Error: linking
return 0;
}
I have a linking error.
Undefined symbols for architecture x86_64:
"SuperDuperBoss::runAI()", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [test] Error 1
Only declare runAI in the derived classes if you want to override the parent's definition. So, assuming you want to use the definition from Enemy, your derived classes should look like this:
class Boss : public Enemy
{
public:
//other bossy stuff
};
class SuperDuperBoss : public Boss
{
public:
//other superduperbossy stuff
};
Related
I am aware that this error usually occurs due to the parent class having a virtual function and that virtual function not being defined in the subclass.
I have , to my knowledge at least defined all the functions bar the function that is supposed to be the signal.
This the .h file for the class
#ifndef HREAD_H
#define HREAD_H
#include "package.h"
#include <QThread>
class hread:public QThread
{
Q_OBJECT
signals:
void transfer(structureData* pkg);
public:
hread();
virtual ~hread();
private:
structureData Send;
bool abort,restart;
protected:
void run() override;
};
#endif // INPUTTHREAD_H
This is my main .cpp file
hread::hread()
{
MutexSend.lock();
restart=false;
abort=false;
MutexSend.unlock();
}
hread::~hread()
{
}
void hread::run()
{
emit transfer(&pkg);
}
I can't quite pinpoint why I got this error.
I'm very new to C++, and I'm trying to use googlemock and googletest. I can't seem to get them to work even in simple examples so I'm sure there must be something simple I'm missing. I would really appreciate some help on this. I have a class Foo which has another class Bar as a dependency so I'm trying to mock this dependency out in tests. I'm sorry in advance, this seems like the simplest Dependency Injection example to me but it still spreads across 9 files! This is Bar:
// lib/bar.h
#ifndef BAR_H
#define BAR_H
class Bar {
public:
Bar(int baz);
virtual ~Bar() {};
int _baz;
};
#endif
With implementation:
// lib/bar.cpp
#include "bar.h"
Bar::Bar(int baz) : _baz(baz) {}
Here is the MockBar header:
// tests/mock_bar.h
#ifndef MOCK_BAR_H
#define MOCK_BAR_H
#include <gmock/gmock.h>
#include "../lib/bar.h"
class MockBar : public Bar {
public:
MockBar();
virtual ~MockBar() {};
};
#endif
And the implementation:
// tests/mock_bar.cpp
#include "mock_bar.h"
MockBar::MockBar() : Bar(0) {
}
So MockBar is just Bar with baz set to 0. Here is Foo:
// lib/foo.h
#ifndef FOO_H
#define FOO_H
#include "bar.h"
class Foo {
public:
Foo(Bar bar);
virtual ~Foo() {};
Bar _bar;
int getBaz();
};
#endif
// lib/foo.cpp
#include "foo.h"
Foo::Foo(Bar bar) : _bar(bar) {
}
int Foo::getBaz() {
return _bar._baz;
}
And here is my test:
// tests/test_foo.h
#ifndef TEST_FOO_H
#define TEST_FOO_H
#include <gtest/gtest.h>
#include "../lib/foo.h"
#include "mock_bar.h"
class FooTest : public ::testing::Test {
public:
FooTest();
Foo subject;
MockBar mock_bar;
virtual ~FooTest() {};
};
#endif
// tests/test_foo.cpp
#include "test_foo.h"
FooTest::FooTest() : mock_bar(), subject(mock_bar) {
}
TEST_F(FooTest, BazTest)
{
ASSERT_TRUE(subject.getBaz() == 0);
}
Finally, the main test function is:
// tests/main.cpp
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "test_foo.h"
int main(int argc, char **argv) {
testing::InitGoogleMock(&argc, argv);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
When I compile this all together with:
g++ tests/main.cpp tests/test_*.cpp tests/mock_*.cpp lib/*.cpp -o test
-lgtest -lpthread -std=c++11
I get the error:
Undefined symbols for architecture x86_64:
"testing::InitGoogleMock(int*, char**)", referenced from:
_main in main-0b53fe.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1
I would really appreciate some help, please let me know if I can be more clear!
You are using parts from gmock but only linking gtest. Thats why InitGoogleMock() is undefined.
Replacing -lgtest with -lgmock should make it.
The reason: gtest is testing framework, gmock the mocking framework.
If you link gmock, its includes also gtest but not the other way round.
I have two classes: AbstractClass and SubClass.
This is basically my code (well, just some example code):
abstractclass.h
class AbstractClass
{
public:
AbstractClass();
void doSomething();
protected:
virtual void implementMe() = 0;
int a;
};
abstractclass.cpp
#include "abstractclass.h"
AbstractClass::AbstractClass(){}
void AbstractClass::doSomething()
{
implementMe(); // compiler error: "implementMe() was not declared in this scope"
a = 0; // same compiler error here...
}
subclass.h
#include "abstractclass.h"
class SubClass : public AbstractClass
{
public:
SubClass();
protected:
void implementMe();
};
subclass.cpp
#include "subclass.h"
SubClass::SubClass() {}
void SubClass::implementMe()
{
// do some stuff
}
In the AbstractClass, however, I keep getting a compiler error (for the virtual function as well as for the class variable):
implementMe() was not declared in this scope
The only way I found to get rid of this was to use forward-declaration:
void implementMe();
AbstractClass::doSomething()
{
implementMe();
}
I cannot believe that this is the correct way, though?
Thanks!
EDIT:
Ok, as my conceptual understanding of subclassing in C++ doesn't seem to be totally wrong (see the comments), I'm gonna share some of my original source code. Hopefully this will help to indentify the error.
This is my abstract / base class:
abstractenvironment.h
#ifndef ABSTRACTENVIRONMENT_H
#define ABSTRACTENVIRONMENT_H
#include <QObject>
class AbstractEnvironment : public QObject
{
Q_OBJECT
public:
AbstractEnvironment(QObject *parent = 0);
protected:
virtual void process() = 0;
quint32 counter;
private slots:
void handleTimeout();
};
#endif // ABSTRACTENVIRONMENT_H
abstractenvironment.cpp
#include "abstractenvironment.h"
#include <QTimer>
QTimer *myTimer;
AbstractEnvironment::AbstractEnvironment(QObject *parent) :
QObject(parent)
{
myTimer = new QTimer(this);
connect(myTimer, &QTimer::timeout, this, &AbstractEnvironment::handleTimeout);
myTimer->start(1);
counter = 0;
}
void handleTimeout()
{
process();
counter++;
}
And this is my subclass:
environment.h
#ifndef ENVIRONMENT_H
#define ENVIRONMENT_H
#include "abstractenvironment.h"
class Environment : public AbstractEnvironment
{
Q_OBJECT
public:
Environment(Controller *controller, QObject *parent = 0);
protected:
void process();
};
#endif // ENVIRONMENT_H
environment.cpp
#include "environment.h"
Environment::Environment(Controller *controller, QObject *parent) :
AbstractEnvironment(controller, parent) {}
void Environment::process()
{
// do something
}
PS: I've learned from the first part of this question and tried to compile the source code above inside Qt with MinGW. I get exactly two error messages (as expected):
..\untitled\abstractenvironment.cpp: In function 'void handleTimeout()':
..\untitled\abstractenvironment.cpp:17:13: error: 'process' was not declared in this scope
..\untitled\abstractenvironment.cpp:18:5: error: 'counter' was not declared in this scope
In case you want to try it yourself, I've zipped the Qt project and uploaded it to my Dropbox (of course I will remove this file at some point but the code is exactly the same as in the post above --> it's just for the sake of convenience, so you don't have to copy-paste it yourself)
EDIT: You just changed your question. So I can't tell if your original text was your actual source code or not. Good rule of thumb, paste your actual code rather than paraphrase it (then de-identify or reduce it if needed).
ORIGINAL ANSWER:
implementMe(); // compiler error: "implementMe() was not declared in this scope"
That is because doSomething() isn't declared properly in AbstractClass. You "declared" it in the base class with:
doSomething();
The compiler doesn't recognize AbstractClass::doSomething() out of line definition so nothing inside the implementation is resolved to the class scope.
Change that to:
void doSomething();
just like in your derived class.
and
AbstractClass::doSomething()
{
implementMe();
}
to
void AbstractClass::doSomething()
{
implementMe();
}
UPDATE:
void handleTimeout()
{
process();
counter++;
}
is a global function. That isn't the class implementation. It should be:
void AbstractClass::handleTimeout()
{
process();
counter++;
}
In abstractenvironment.cpp you define void handleTimeout(), which is non-member function and does not relate to AbstractEnvironment class. Thus, it doesn't look for AbstractEnvironment::process() and AbstractEnvironment::counter, but for ::process() and ::counter instead (which are not declared, hence the error).
Change it to void AbstractEnvironment::handleTimeout() and it should compile.
I have a problem with a static library build with Xcode 4.6.2 using the LLVM Clang Compiler. The problem occurs only if I use the C/C++ Compiler flag visibility=hidden. The Linker reports me a duplicate symbol error. I will explain the setup in an easy scenario and I hope someone can explain why this happen.
Imagine I have two classes ClassA and ClassB which I compile into a static library myLib. As said above, I set the Compiler flag -fvisibility=hidden.
Then I have a project which creates an executable from a main.cpp which uses the myLib.
Here are the classes:
ClassA.h
#pragma once
#include <boost/exception/all.hpp>
struct my_error : virtual std::exception, virtual boost::exception {};
class ClassA
{
public:
explicit ClassA() {};
virtual ~ClassA() {};
virtual void doSomething();
};
ClassA.cpp
#include "ClassA.h"
void ClassA::doSomething()
{
BOOST_THROW_EXCEPTION( my_error() << boost::errinfo_api_function("doSomething") );
}
ClassB.h
#pragma once
#include "ClassA.h"
class ClassB
{
public:
explicit ClassB() {};
virtual ~ClassB() {};
virtual void doSomething();
};
ClassB.cpp
#include "ClassB.h"
void ClassB::doSomething()
{
BOOST_THROW_EXCEPTION( my_error() << boost::errinfo_api_function("doSomething") );
}
These two classes a build into my library without a problem. In my executable project which links the myLib I have the following main.cpp
main.cpp
#include <iostream>
#include "ClassA.h"
#include "ClassB.h"
int main(int argc, const char * argv[])
{
ClassA A;
ClassB B;
return 0;
}
The C++ flags:
The build results in the following errors:
duplicate symbol __ZTIPN5boost21errinfo_api_function_E in:
/Users/georg/Library/Developer/Xcode/DerivedData/ExceptionTest-dcnvciwqbwqvciaokkjjaqchftll/Build/Products/Debug/libExceptionLib.a(ClassA.o)
/Users/georg/Library/Developer/Xcode/DerivedData/ExceptionTest-dcnvciwqbwqvciaokkjjaqchftll/Build/Products/Debug/libExceptionLib.a(ClassB.o)
duplicate symbol __ZTSPN5boost21errinfo_api_function_E in:
/Users/georg/Library/Developer/Xcode/DerivedData/ExceptionTest-dcnvciwqbwqvciaokkjjaqchftll/Build/Products/Debug/libExceptionLib.a(ClassA.o)
/Users/georg/Library/Developer/Xcode/DerivedData/ExceptionTest-dcnvciwqbwqvciaokkjjaqchftll/Build/Products/Debug/libExceptionLib.a(ClassB.o)
ld: 2 duplicate symbols for architecture i386 clang: error: linker
command failed with exit code 1 (use -v to see invocation)
If I change the Compiler Flags to the following it works:
The problem is the boost::errinfo_api_function object, but I do not understand why?
I hope someone can help me.
Kind Regards
Georg
I know the question have been asked tons of times but I can't find the solution here nor in google.
Here's my header file
#ifndef MAINCONTROLLER_H
#define MAINCONTROLLER_H
#include <QSettings>
#include <QDebug>
#include <QDir>
#include <QObject>
#include "PhTools/PhString.h"
#include "PhStrip/PhStripDoc.h"
class MainController : public QObject
{
Q_OBJECT
public:
explicit MainController(QObject *parent = 0);
void loadSettings();
PhString getLastFile();
void setLastFile(PhString fileName);
bool openDoc(PhString fileName);
signals:
void docChanged();
private:
QSettings * _settings;
PhStripDoc * _doc;
};
#endif // MAINCONTROLLER_H
And my CPP file :
#include "MainController.h"
MainController::MainController(QObject *parent) :
QObject(parent)
{
_doc = new PhStripDoc();
loadSettings();
}
void MainController::loadSettings()
{
_settings = new QSettings(QDir::homePath() + "/Library/Preferences/com.me.me.plist", QSettings::NativeFormat);
getLastFile();
}
PhString MainController::getLastFile()
{
qDebug() << "lastfile :" << _settings->value("last_file", "").toString();
return _settings->value("last_file").toString();
}
bool MainController::openDoc(PhString fileName)
{
bool succeed = _doc->openDX(fileName);
if (succeed)
emit docChanged();
return succeed;
}
void MainController::setLastFile(PhString filename)
{
_settings->setValue("last_file", filename);
}
And here's the error log :
Undefined symbols for architecture x86_64:
"MainController::docChanged()", referenced from:
MainController::openDoc(QString) in MainController.o
"vtable for MainController", referenced from:
MainController::MainController(QObject*) in MainController.o
MainController::MainController(QObject*) in MainController.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
It might come from signals but I'm not sure...
When the Q_OBJECT macro is added after the code has already been compiled, qmake has to be run again. This will add the creation and compilation of MainController.moc to your Makefile thus preventing the linker error.
You need to include this line at the end of your source file:
#include "MainController.moc"
Alternatively, you can also handle this with your buildsystem, but that is probably the former is easier.