Why virtual function has to be implemented in superclass? - c++

I am trying to compile the following code:
#include <iostream>
class X{
public:
virtual void func();
};
class Y : public X{
public:
virtual void func(){
std::cout << "y" << std::endl;
}
};
int main(){
Y* y = new Y();
y->func();
return 0;
}
But building fails (on Xcode - C++11) with the following messages:
Undefined symbols for architecture x86_64:
"typeinfo for X", referenced from:
typeinfo for Y in c.o
"vtable for X", referenced from:
X::() in c.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)
However, as soon as I add an implementation for func in X, it builds successfully. I am pretty sure, that virtual method is optional to be implemented in the superclass but I don't understand why is this happening. Also, if comment the code in main(), it builds successfully. I am assuming that the problem is calling the func() in main, but Xcode doesn't list it as runtime error, it only says build-time error.

If you don't want to implement the virtual function in the base class at all, simply mark it as pure virtual:
virtual void func() = 0;

No, you are wrong. You need to have implementations for non-pure virtual functions. If you do not want to provide an implementation, you need to make function pure virtual, using = 0 syntax.

Related

C++ can't define virtual function OUTSIDE classes and header file

As function name had been already declared in header file: function.h and header file were preloaded in OJ, I need to define myAdd in main.cpp, aka OUTSIDE classes. However, most tutorial I can find online about virtual function just define what the function should do INSIDE the class.This is header file:
#ifndef _FUNCTION_H_
#define _FUNCTION_H_
class abstractAdd
{
public:
abstractAdd(){};
~abstractAdd(){};
virtual int myAdd(int a, int b) = 0;
};
class Implement : public abstractAdd
{
private:
public:
Implement();
~Implement();
int myAdd(int a,int b);
};
;
#endif
I have tried this in main.cpp
//include every libraries needed
#include "function.h"
int Implement::myAdd(int a,int b)
{
int c=a+b;
return c;
}
int main(){
abstractAdd& ra = *new Implement();
string input;
while(getline(std::cin, input)){
istringstream testcase(input);
int a,b;
testcase >> a;
testcase >> b;
cout << ra.myAdd(a,b) << endl;
}
return 0;
}
But compiler said:
Undefined symbols for architecture x86_64:
"Implement::Implement()", referenced from:
_main in cc3KANpW.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
How can I implement the function OUTSIDE classes and header files?
new Implement() will create an object. That entails calling the constructor. You declared a constructor Implement();, but didn't define it anywhere.
So the linker is complaining because it can't find the constructor definition.
If you simply wish to use the default constructor as a compiler would define it, you can declare it as follows:
Implement() = default;
It will be defaulted, and defined inline.
Same goes for Implement's destructor as well.
As an aside, while your program is small and probably hosted, it still contains a leak. You allocate with new but don't delete the created object. In real production code, that will be unacceptable. You can simplify your code and rid you self of this concern by using a smart pointer:
std::unique_ptr<abstractAdd> ra = std::make_unique<Implement>();
Now that the object is disposed of correctly when the time comes, you should also make the destructor of abstractAdd virtual as well. Because now you are destroying an object polymorphically.

C++ linker warning because of virtual destructor / clang

I'm getting a linker warning caused by virtual destructors. My environment is the KEIL compiler v6.5 (clang).
Warning: L6439W: Multiply defined Global Symbol __clang_call_terminate defined in invalid_group(new.cpp.o) rejected in favor of Symbol defined in .text.__clang_call_terminate(cxa_handlers.cpp.o).
I get this warning as soon as I add the virtual destructor to an interface. For example:
class IInterface {
virtual ~IInterface(){}
virtual void doSomething() const = 0;
}
As soon as I implement one single derived class of this interface I get the above mentioned warning. As soon as I remove the virtual destructor, the warning vanishes.
I tried really many things to find out what's the reason, but didn't succeed...
Does someone know how to fix this warning?
Thank you!
Edit: A complete example throwing this warning:
class IInterface {
public:
virtual ~IInterface();
virtual void doSomething() = 0;
};
IInterface::~IInterface() {
}
class SomeClass : public IInterface {
public:
virtual void doSomething();
};
void SomeClass::doSomething() {
}
int main() {
}
I asked support of ARM and got the information that this warning is spurious. So it seems to be an issue of the current ARM clang compiler toolchain implementation.
Nevertheless thank you all for your responses on this topic.
If you define your function in header you will emit the function each time you include it in a file. To remove this warming you need to define your method outside the declaration
// IInterface.hpp
class IInterface {
public:
virtual ~IInterface();
}
// IInterface.cpp
IInterface::~IInterface() {}
As mentioned, this was a linker bug which has been fixed in ARM Compiler v6.11 (10/25/2018).
Release notes:
[SDCOMP-30157] In certain circumstances, after discarding a section from a COMDAT ELF section group, the linker could incorrectly report Warning: L6439W: Multiply defined Global Symbol defined in invalid_group() rejected in favour of Symbol defined in (). This has been fixed.

Template inheritance in C++ and undefined symbols on Xcode

I have seen many related questions to this problem, but after carefully following advice from members, my problem still persists. The code is quite simple. I only have the following header file ("instrument.h"), which contains the base class and the template class:
#include <stdio.h>
#include <string>
using namespace std;
class Instrument
{
public:
Instrument();
virtual void print() const = 0;
};
template <class parameter> class Equity : public Instrument
{
public:
Equity();
virtual void print() const;
};
Now, in my main function on main.cpp I only do the following:
#include "instrument.h"
#include <iostream>
int main() {
Equity<double> pb;
return 0;
}
Well, I get the very well-known error:
Undefined symbols for architecture x86_64:
"Equity<double>::Equity()", 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)
I have already changed in Build Settings the C++ standard library to libstdc++, also to default compiler, and so on. Do I have a problem with my project settings? Is perhaps the template wrongly implemented? I was thinking I should also have a instrument.cpp file, but then again definitions for templates must be kept in the header file so that would probably crash too.
Thanks in advance
You declared the default constructors for both Instrument and Equity but defined them nowhere.
Alter their definitions appropriately:
public:
Equity() = default; // Or {} in pre-C++11
// ^^^^^^^^^
(And equivalently for Instrument)
You can also completely omit the declarations of any default constructors for now since you didn't declare any other constructors in both Equity and Instrument and the default constructors will be generated automatically.

Trying to create instance of class throws vtable error in XCode

I am trying to create an instance of a the following class:
#ifndef Sik_GameEntity_h
#define Sik_GameEntity_h
class GameEntity {
public:
~GameEntity(){};
void setup();
void update();
void draw();
void clear();
protected:
private:
};
#endif
Each of these methods (minus the deconstructor) are fleshed out in my .cpp file.
for ( int i = 0; i < nEntities; i++ )
{
GameEntity ent;
ent.setup();
entities.push_back(ent);
}
I'm creating an instance and inserting it into a vector of Game Entity objects. When I create an instance, I get the following error from XCode:]
Undefined symbols for architecture i386:
"GameEntity::GameEntity()", referenced from:
appCore::setup() in appCore.o
"GameEntity::~GameEntity()", referenced from:
appCore::setup() in appCore.o
std::vector<GameEntity, std::allocator<GameEntity> >::_M_insert_aux(__gnu_cxx::__normal_iterator<GameEntity*, std::vector<GameEntity, std::allocator<GameEntity> > >, GameEntity const&) in appCore.o
void std::_Destroy<GameEntity>(GameEntity*) in appCore.o
"vtable for GameEntity", referenced from:
GameEntity::GameEntity(GameEntity const&) in appCore.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture i386
I've tried adding a constructor, but it didn't make a difference, I still received the same errors. Is it obvious what I'm doing wrong in my class?
EDIT:
I forgot to mention, I cleaned my build.
The following NOTE and error means that you are trying to inline the constructor or setup method in your cpp file rather than the header file. Remove all inline keywords in your cpp file
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture i386

undefined reference to vtable - virtual member, classes generated by gsoap

gsoap with its tools wsdl2h and soapcpp2 provided me with a soapStub.h file containing the following:
class SOAP_CMAC ns2__SOAPKunden
{
public:
std::string *adresszusatz;
// ...
public:
virtual int soap_type() const { return 7; }
// ...
ns2__SOAPKunden() : adresszusatz(NULL), x(NULL) { } // left out all member init.
virtual ~ns2__SOAPKunden() { }
};
I start with a small app using the class to populate objects with data from informix DB.
But to compile successfully i have to leave away all the virtual stuff - i found many postings about this error and use of virtual members in subclasses - otherwise i get
main.o: In function `ns2__SOAPKunden::ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenC1Ev[ns2__SOAPKunden::ns2__SOAPKunden()]+0xf): undefined reference to `vtable for ns2__SOAPKunden'
main.o: In function `ns2__SOAPKunden::~ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenD1Ev[ns2__SOAPKunden::~ns2__SOAPKunden()]+0x13): undefined reference to `vtable for ns2__SOAPKunden'
collect2: ld returned 1 exit status
I admit after years of scripting only it's very hard for me to make sense of C++ code... I want to ask for any advice what to try next. My class is no derived class, is for example what makes me wonder.
The error means that the virtual table has not been correctly compiled/linked in the final binary (executable or library). There are two common circumstances that lead to this error:
you are not linking the object file that includes the virtual table definitions --i.e. you compiled soapStub.cpp into soapStub.o, but did not add that binary to the linker command line.
the compiler is not generating the virtual table anywhere, so even if you are including all object files, that does not include the virtual table.
The second case is the hardest to identify for non-experienced developers, and can be caused by a class that is defined in the header and contains virtual functions. If all the virtual functions are defined inlined, the compiler will generate the virtual table in all translation units that include the header, and mark it as a weak symbol so that the linker can discard them, but if you later add a new virtual method and you leave it undefined in the header --or if you remove the definition from one of the virtual functions--, then the compiler will not generate the virtual table in each translation unit, but only in the one that defines those functions.
Things to check:
you are linking all object files
either all virtual functions are defined inline in the class definition or you have a .cpp that defines the virtual functions and you are linking that in.
This is what David Rodriguez said, just stated simpler I guess...
I had this situation in my interface class:
class IBase
{
public:
virtual void begin(unsigned long);
virtual void end();
virtual int available(void) = 0;
virtual int peek(void) = 0;
virtual int read(void) = 0;
virtual void flush(void) = 0;
}
and changed it to this:
class IBase
{
public:
virtual void begin(unsigned long) = 0;
virtual void end() = 0;
virtual int available(void) = 0;
virtual int peek(void) = 0;
virtual int read(void) = 0;
virtual void flush(void) = 0;
}
which did the trick.
begin() and end() were defined in derived class in a different file, IBase class (interface) was only declared in header and included in few places.
Error from OP only appeared when I set optimizations to none (-O0), any other setting resulted in no error (gcc 4.8).