So, I have an abstract class Panel and an implementation of it MyPanel. They look similar to this:
class Panel : public QWidget
{
public:
Panel(QWidget* parent = 0) = 0;
virtual ~Panel() = 0;
// but wait, there's more!!
};
class MyPanel : public Panel
{
public:
MyPanel(QWidget* parent = 0);
~MyPanel() {}; // nothing to do here
};
MyPanel::MyPanel(QWidget* parent) :
Panel(parent)
{
// you must construct additional pylons
}
I'm getting linker errors for the constructor/destructor from VC++
error LNK2019: unresolved external symbol "public: virtual __thiscall Panel::~Panel(void)" (??1Panel##UAE#XZ) referenced in function "public: virtual __thiscall MyPanel::~MyPanel(void)" (??1MyPanel##UAE#XZ) mypanel.obj
error LNK2019: unresolved external symbol "public: __thiscall Panel::Panel(class QWidget *)" (??0Panel##QAE#PAVQWidget###Z) referenced in function "public: __thiscall MyPanel::MyPanel(class QWidget *)" (??0MyPanel##QAE#PAVQWidget###Z) mypanel.obj
Why am I getting this linker error?
--- THE ANSWER ---
class Panel : public QWidget
{
public:
Panel(QWidget* parent = 0) : QWidget(parent) {};
virtual ~Panel() {};
// but wait, there's more!!
};
I thought I had tried this before lunch. Turns out I was wrong.
there is no such thing like virtual constructor.
You still should provide implementation of destructor.
Purely virtual destructors still need to have an implementation.
To expand on that a bit:
The destructor of a class will always be called if any instance of a subclass gets destructed, so it needs to have an implementation. (Basically the only effect of making a destructor purely virtual is that it prevents instanatiation of the class).
As for the constructor: You're making it purely virtual (which I don't see any reason for doing), but then you explicitly call it from the subclass's constructor.
Related
I tried to override the mouseMoveEvent method by subclassing ChartView and I get a linking error which has something to do with the constructor of ChartView class.
class ChartView : public QChartView
{
Q_OBJECT
public:
ChartView(QChart* chart, QWidget* parent = 0);
protected:
void mouseMoveEvent(QMouseEvent* event) override;
};
ChartView::ChartView(QChart* chart, QWidget* parent)
: QChartView(chart, parent)
{
this->setMouseTracking(true);
}
void ChartView::mouseMoveEvent(QMouseEvent* event)
{
qDebug() << event->pos();
}
The error:
1>mainwindow.obj : error LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __cdecl ChartView::metaObject(void)const " (?metaObject#ChartView##UEBAPEBUQMetaObject##XZ)
1>mainwindow.obj : error LNK2001: unresolved external symbol "public: virtual void * __cdecl ChartView::qt_metacast(char const *)" (?qt_metacast#ChartView##UEAAPEAXPEBD#Z)
1>mainwindow.obj : error LNK2001: unresolved external symbol "public: virtual int __cdecl ChartView::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall#ChartView##UEAAHW4Call#QMetaObject##HPEAPEAX#Z)
When I remove the constructor of ChartView, the problem is gone, but I dont know why, because I also dont understand the error.
What am I doing wrong and how can I fix this problem?
Before building your application, you need to clean qmake and run it again. Then, you can rebuild the solution. Problem is fixed.
Here's my abstract class Storestate.h:
#ifndef STORESTATE_H_
#define STORESTATE_H_
class Store;
class StoreState
{
public:
virtual void Close(Store&);
virtual void Open(Store&);
virtual void Sell(Store&);
};
#endif
The Derived class header file ConcreteStateOpened.h:
#ifndef CONCRETESTATEOPENED_H_
#define CONCRETESTATEOPENED_H_
#include "StoreState.h"
#include "Store.h"
class ConcreteStateOpened : public StoreState
{
public:
ConcreteStateOpened() {}
void Open(Store&) override;
void Close(Store&) override;
void Sell(Store&) override;
};
#endif
The Dervied class cpp file ConcreteStateOpened.cpp:
#include "ConcreteStateOpened.h"
#include <iostream>
using namespace std;
void ConcreteStateOpened::Open(Store &store)
{
cout << store.Name << " is already opened!" << endl;
}
void ConcreteStateOpened::Close(Store &store)
{
store.State = ConcreteStateOpened();
}
void ConcreteStateOpened::Sell(Store &store)
{
std::cout << "Sell Opened";
}
I don't know how to fix this. I tried removing override keywords, aswell as virtual ones. Even removing the definition etc. I just need help from pros :,)
Here are the unresolved external symbol errors:
1>ConcreteStateOpened.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Close(class Store &)" (?Close#StoreState##UAEXAAVStore###Z)
1>Data.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Close(class Store &)" (?Close#StoreState##UAEXAAVStore###Z)
1>StateStore.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Close(class Store &)" (?Close#StoreState##UAEXAAVStore###Z)
1>ConcreteStateOpened.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Open(class Store &)" (?Open#StoreState##UAEXAAVStore###Z)
1>Data.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Open(class Store &)" (?Open#StoreState##UAEXAAVStore###Z)
1>StateStore.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Open(class Store &)" (?Open#StoreState##UAEXAAVStore###Z)
1>ConcreteStateOpened.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Sell(class Store &)" (?Sell#StoreState##UAEXAAVStore###Z)
1>Data.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Sell(class Store &)" (?Sell#StoreState##UAEXAAVStore###Z)
1>StateStore.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Sell(class Store &)" (?Sell#StoreState##UAEXAAVStore###Z)
1>D:\Local-Git-Repos\DesignPatterns\StateC++\StateStore\Debug\StateStore.exe : fatal error LNK1120: 3 unresolved externals
You didn't make the methods in the abstract base pure virtual.
Also you should add : public virtual destructor, protected default constructor and remove copy/move/assignment constructors
#ifndef STORESTATE_H_
#define STORESTATE_H_
class Store;
class StoreState
{
public:
virtual ~StoreState() = default;
StoreState(const StoreState&) = delete;
StoreState(StoreState&&) = delete;
StoreState& operator=(const StoreState&) = delete;
virtual void Close(Store&) = 0;
virtual void Open(Store&) = 0;
virtual void Sell(Store&) = 0;
protected:
StoreState() = default; // prevent accidental creation
};
#endif
Your StoreState isn't actually abstract. You have declared Close, Open, Sell as actual virtual functions with definitions. To declare a virtual function with no definition in that class, use the "pure virtual" syntax = 0.
Also, it's best practice for a polymorphic class type to have a virtual destructor. And per the Rule Of Five, when you declare a destructor, be sure to think about the copy/move constructor and copy/move assignment. For an interface class, it's often best to just make it uncopyable and unassignable.
class StoreState
{
public:
StoreState() = default;
StoreState(const StoreState&) = delete;
StoreState& operator=(const StoreState&) = delete;
virtual ~StoreState() = default;
virtual void Close(Store&) = 0;
virtual void Open(Store&) = 0;
virtual void Sell(Store&) = 0;
};
For starters there is no abstract class in the presented code by you because the class StoreState does not contain pure virtual functions.
From the C++ 20 Standard (11.7.3 Abstract classes)
2 A virtual function is specified as a pure virtual function by using
a pure-specifier (11.4) in the function declaration in the class
definition. [Note: Such a function might be inherited: see below. —
end note] A class is an abstract class if it has at least one pure
virtual function. [Note: An abstract class can be used only as a
base class of some other class; no objects of an abstract class can be
created except as subobjects of a class derived from it (6.2, 11.4). —
end note] A pure virtual function need be defined only if called with,
or as if with (11.4.6), the qualified-id syntax
You need either to provide definitions of the virtual functions declared in the class StoreState or to make them pure virtual functions like for example
class StoreState
{
public:
virtual void Close(Store&) = 0;
virtual void Open(Store&) = 0;
virtual void Sell(Store&) = 0;
};
Even if a function is declared as a pure virtual function nevertheless you may provide its definition (outside the class definition where it is declared as a pure virtual function) if it is required.
Pay attention to that when you have polymorphic classes then you should declare the destructor also as virtual. For example
class StoreState
{
public:
virtual ~StoreState() = default;
virtual void Close(Store&) = 0;
virtual void Open(Store&) = 0;
virtual void Sell(Store&) = 0;
};
You may need to add virtual to the concrete class methods
#ifndef CONCRETESTATEOPENED_H_
#define CONCRETESTATEOPENED_H_
#include "StoreState.h"
#include "Store.h"
class ConcreteStateOpened : public StoreState
{
public:
ConcreteStateOpened() {}
virtual void Open(Store&) override;
virtual void Close(Store&) override;
virtual void Sell(Store&) override;
};
#endif
I am trying to create a class library dll that exports a template class. I have a local version of the same class and it must be coincidental, but it works correctly. I know this doesn't really mean much, clearly something is wrong.
The exported template class in the library dll is:
template <class CcmBlock>
class CCMSHARED_EXPORT CcmFilter
{
public:
CcmFilter()
{
mBlock = nullptr;
////mBlockList = new std::list<CcmBlock*>();
}
void add(CcmFrame* frame)
{
if (frame == nullptr)
return;
mBlock = new CcmBlock(
frame->getFrameData(),
frame->getSampleRate(),
0xFFFFFFFF,
frame->getBlockSize(),
frame->getDomain()
);
mBlockList->push_back(aBlock);
}
CcmBlock* get()
{
return mBlock;
}
private:
CcmBlock* mBlock;
////std::list<CcmBlock*>* mBlockList;
};
On the application side:
CcmFilter<FooBlock>* oneFilter = new CcmFilter<FooBlock>();
//Filter<Block>* filter = new Filter<Block>();
CcmFrame* frame = new CcmFrame(0, 50000, 40, 1024, Domain::Time);
oneFilter->add(frame);
CcmBlock* block = oneFilter->get();
FooBlock* fooBlock = dynamic_cast<FooBlock*>(block);
if (fooBlock == nullptr)
{ //Report Error }
else
{ // Do the work}
and the FooBlock class is derived from CcmBlock as follows:
class FooBlock : public CcmBlock
{
public:
FooBlock(int* ipblock, DWORD dwSampleRate, DWORD dwMicrophoneIndex, DWORD dwBlockSize, Domain domain);
void process();
};
The library compiles and builds the dll. When I attempt to build the application I get messages:
mainwindow.obj:-1: error: LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl CcmFilter::CcmFilter(void)" (__imp_??0?$CcmFilter#VFooBlock####QEAA#XZ) referenced in function "public: __cdecl MainWindow::MainWindow(class QWidget *)" (??0MainWindow##QEAA#PEAVQWidget###Z)
mainwindow.obj:-1: error: LNK2019: unresolved external symbol "__declspec(dllimport) public: void __cdecl CcmFilter::add(class CcmFrame *)" (__imp_?add#?$CcmFilter#VFooBlock####QEAAXPEAVCcmFrame###Z) referenced in function "public: __cdecl MainWindow::MainWindow(class QWidget *)" (??0MainWindow##QEAA#PEAVQWidget###Z)
DLL-s are loaded at runtime, while templates are instantiated at compile time.
A work-around which is not ideal but might work for a very limited use case is to explicitly instantiate a template somewhere after their declaration. That is, add something like:
template class CcmFilter<FooBlock>;
For details, see https://msdn.microsoft.com/en-us/library/by56e477(VS.80).aspx
Just do not use declspec. But in your case template will be compiled each time when you include it in *.cpp file. It wont be exported.
In order to export some well-known implementations of your template you probably should use template explicit instantiation definitions in tandem with __declspec(export).
I'm creating a mod for Half Life 2 and want to add a method from physcannon.cpp to the crossbow.cpp. I first tried making the physcannon class a friend class of the crossbow class, including the physcannon.cpp in the crossbow cpp then calling one of physcannon's methods inside one of crossbow's methods but get the below errors (this is just a few of a the many similar errors). Part of Crossbow's class looks like this and I think the errors were caused by the includes of both cpp files overlapping somehow. Is there a different C++ technique I could use here to call the Force() method of the physcannon class in the crossbow class?
class CWeaponCrossbow : public CBaseHLCombatWeapon
{
DECLARE_CLASS( CWeaponCrossbow, CBaseHLCombatWeapon );
public:
CWeaponCrossbow( void );
virtual void Precache( void );
virtual void PrimaryAttack( void );
virtual void SecondaryAttack( void );
virtual void Force( void ) { CWeaponPhysCannon A; A.Force(); };
virtual bool Deploy( void );
virtual void Drop( const Vector &vecVelocity );
virtual bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
virtual bool Reload( void );
virtual void ItemPostFrame( void );
virtual void ItemBusyFrame( void );
virtual void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator );
virtual bool SendWeaponAnim( int iActivity );
virtual bool IsWeaponZoomed() { return m_bInZoom; }
1>weapon_physcannon.obj : error LNK2005: "public: static struct datamap_t * __cdecl game_shadowcontrol_params_t::GetBaseMap(void)" (?GetBaseMap#game_shadowcontrol_params_t##SAPAUdatamap_t##XZ) already defined in weapon_crossbow.obj
1>weapon_physcannon.obj : error LNK2005: "private: static struct datamap_t * __cdecl CGrabController::GetBaseMap(void)" (?GetBaseMap#CGrabController##CAPAUdatamap_t##XZ) already defined in weapon_crossbow.obj
1>weapon_physcannon.obj : error LNK2005: "public: void __thiscall CGrabController::OnRestore(void)" (?OnRestore#CGrabController##QAEXXZ) already defined in weapon_crossbow.obj
1>weapon_physcannon.obj : error LNK2005: "public: virtual enum IMotionEvent::simresult_e __thiscall CGrabController::Simulate(class IPhysicsMotionController *,class IPhysicsObject *,float,class Vector &,class Vector &)" (?Simulate#CGrabController##UAE?AW4simresult_e#IMotionEvent##PAVIPhysicsMotionController##PAVIPhysicsObject##MAAVVector##2#Z) already defined in weapon_crossbow.obj
1>weapon_physcannon.obj : error LNK2005: "private: virtual struct datamap_t * __thiscall CPlayerPickupController::GetDataDescMap(void)" (?GetDataDescMap#CPlayerPickupController##EAEPAUdatamap_t##XZ) already defined in weapon_crossbow.obj
1>weapon_physcannon.obj : error LNK2005: "public: static struct datamap_t * __cdecl thrown_objects_t::GetBaseMap(void)" (?GetBaseMap#thrown_objects_t##SAPAUdatamap_t##XZ) already defined in weapon_crossbow.obj
1>weapon_physcannon.obj : error LNK2005: "public: virtual class ServerClass * __thiscall CWeaponPhysCannon::GetServerClass(void)" (?GetServerClass#CWeaponPhysCannon##UAEPAVServerClass##XZ) already defined in weapon_crossbow.obj
1>weapon_physcannon.obj : error LNK2005: "public: virtual int __thiscall CWeaponPhysCannon::YouForgotToImplementOrDeclareServerClass(void)" (?YouForgotToImplementOrDeclareServerClass#CWeaponPhysCannon##UAEHXZ) already defined in weapon_crossbow.obj
1>weapon_physcannon.obj : error LNK2005: "public: virtual struct datamap_t * __thiscall CWeaponPhysCannon::GetDataDescMap(void)" (?GetDataDescMap#CWeaponPhysCannon##UAEPAUdatamap_t##XZ) already defined in weapon_crossbow.obj
1>weapon_physcannon.obj : error LNK2005: "public: virtual void __thiscall CWeaponPhysCannon::WeaponIdle(void)" (?WeaponIdle#CWeaponPhysCannon##UAEXXZ) already defined in weapon_crossbow.obj
EDIT:
For greatwolf: CWeaponCrossbow and CWeaponPhysCannon both inherit from CbaseHLCombatWeapon and override function etc etc. I am attempting to add one of the functions in CWeaponPhysCannon to be usable in the CWeaponCrossbow class (and eventually all other weapons will also get this added method).
I like the idea of having an intermediate base class as suggested by Tristan Brindle and will be attempting that. Does the intermediate base class only need the
virtual void Force( void ) { CWeaponPhysCannon A; A.Force(); };
I am trying to implement into the crossbow or do I need to put in every placeholder function as well? (not new to polymorphism but not experienced either) Thanks!
You can't just include "physcannon.cpp" inside "crossbow.cpp". Doing so will result in duplicate definitions of things inside "physcannon.cpp", which is causing the errors you're seeing at link-time.
If what you want is to use some private functions defined inside the physcannon.cpp file, try to move them to a separate file with its own header. You can then include the header in both "physcannon.cpp" and "crossbow.cpp". Alternatively, if the functions are small, put the definitions in the header and make them inline.
If what you want is to use PhysCannon methods in your Crossbow class, then this won't work. The best thing you can do in this case is to move these methods to an intermediate base class, like
class CHLCombatWeaponWithSomePhysics : public CBaseHLCombatWeapon
{
// Define some methods that were previously in PhysCannon
};
Then change both physcannon and crossbow so they inherit from this intermediate class.
1>main.obj : error LNK2019: unresolved external symbol "public: virtual bool __thiscall LinkedSortedList<int>::getfirst(int &)" (?getfirst#?$LinkedSortedList#H##UAE_NAAH#Z) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: virtual void __thiscall LinkedSortedList<int>::clear(void)" (?clear#?$LinkedSortedList#H##UAEXXZ) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: virtual void __thiscall LinkedSortedList<int>::print(void)const " (?print#?$LinkedSortedList#H##UBEXXZ) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: virtual bool __thiscall LinkedSortedList<int>::insert(int)" (?insert#?$LinkedSortedList#H##UAE_NH#Z) referenced in function _main
1>main.obj : error LNK2001: unresolved external symbol "public: virtual bool __thiscall LinkedSortedList<int>::find(int)const " (?find#?$LinkedSortedList#H##UBE_NH#Z)
1>main.obj : error LNK2001: unresolved external symbol "public: virtual int __thiscall LinkedSortedList<int>::size(void)const " (?size#?$LinkedSortedList#H##UBEHXZ)
1>c:\users\chris\documents\visual studio 2010\Projects\lab0\Debug\lab0.exe : fatal error LNK1120: 6 unresolved externals
This is what I recieve when trying to compile my code. I've narrowed it down to (i believe) this section of code here:
#ifndef _LinkedSortedListClass_
#define _LinkedSortedListClass_
#include "LinkedNode.h"
#include "SortedList.h"
template <class Elm>
class LinkedSortedList: public SortedList<int> {
public:
void clear();
bool insert(Elm newvalue);
bool getfirst(Elm &returnvalue);
void print() const;
bool find(Elm searchvalue) const;
int size() const;
private:
LinkedNode<Elm>* head;
};
#endif
This is the child class of the SortedList, which is this, in case it's needed..
#ifndef _SortedListClass_
#define _SortedListClass_
template <class Elm> class SortedList {
public:
// -------------------------------------------------------------------
// Pure virtual functions -- you must implement each of the following
// functions in your implementation:
// -------------------------------------------------------------------
// Clear the list. Free any dynamic storage.
virtual void clear() = 0;
// Insert a value into the list. Return true if successful, false
// if failure.
virtual bool insert(Elm newvalue) = 0;
// Get AND DELETE the first element of the list, placing it into the
// return variable "value". If the list is empty, return false, otherwise
// return true.
virtual bool getfirst(Elm &returnvalue) = 0;
// Print out the entire list to cout. Print an appropriate message
// if the list is empty. Note: the "const" keyword indicates that
// this function cannot change the contents of the list.
virtual void print() const = 0;
// Check to see if "value" is in the list. If it is found in the list,
// return true, otherwise return false. Like print(), this function is
// declared with the "const" keyword, and so cannot change the contents
// of the list.
virtual bool find(Elm searchvalue) const = 0;
// Return the number of items in the list
virtual int size() const = 0;
};
#endif
Thanks so much for any help; our last class taught us nothing of inheritance, but this is project #1 for this class, without being taught inheritance here either, so this is all touch and go for me, despite what I managed to look up on Google.
Your methods aren't defined. So the linker is complaining because it can't link to their definitions.
Maybe it helps if you placed the definitions of your functions in your header file. This makes it easier for the compiler to resolve these external symbols.
I hope this will help.
Regards,
Philinator