Greetings all,
I come from Java background and I am having difficulty with multiple inheritance.
I have an interface called IView which has init() method.I want to derive a new class called PlaneViewer implementing above interface and extend another class. (QWidget).
My implementation is as:
IViwer.h (only Header file , no CPP file) :
#ifndef IVIEWER_H_
#define IVIEWER_H_
class IViewer
{
public:
//IViewer();
///virtual
//~IViewer();
virtual void init()=0;
};
#endif /* IVIEWER_H_ */
My derived class.
PlaneViewer.h
#ifndef PLANEVIEWER_H
#define PLANEVIEWER_H
#include <QtGui/QWidget>
#include "ui_planeviewer.h"
#include "IViewer.h"
class PlaneViewer : public QWidget , public IViewer
{
Q_OBJECT
public:
PlaneViewer(QWidget *parent = 0);
~PlaneViewer();
void init(); //do I have to define here also ?
private:
Ui::PlaneViewerClass ui;
};
#endif // PLANEVIEWER_H
PlaneViewer.cpp
#include "planeviewer.h"
PlaneViewer::PlaneViewer(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
}
PlaneViewer::~PlaneViewer()
{
}
void PlaneViewer::init(){
}
My questions are:
Is it necessary to declare method init() in PlaneViewer interface also , because it is already defined in IView?
2.I cannot complie above code ,give error :
PlaneViewer]+0x28): undefined reference to `typeinfo for IViewer'
collect2: ld returned 1 exit status
Do I have to have implementation for IView in CPP file (because all I want is an interface,not as implementation) ?
A good way to think about interface classes is that they specify what methods derived classes MUST implement.
Is it necessary to declare method
init() in PlaneViewer interface also ,
because it is already defined in
IView?
The quick answer is that yes you must implement the init method in IViewer because in the base class the method is declared as pure virtual. This means that any derived class MUST provide its own implementation of that method as there is no base class method implemented.
2.I cannot complie above code ,give error :
PlaneViewer]+0x28): undefined
reference to `typeinfo for IViewer'
collect2: ld returned 1 exit status
This is a g++ compiler error that indicates (as stated above) that you have a derived class from a base that has a pure virtual function and that the derived class does not implement the pure virtual method, as it must.
Oh and it should also be noted that you are not having an issue with multiple inheritance, the problem would still exist if only IViewer and PlaneViewer were involved.
Yes, you have to declare init in your PlaneViewer as well. If you didn't, then init wouldn't exist in PlaneViewer and PlaneViewer would still be considered abstract (because there's no implementation of init).
You need to define empty bodies for your (virtual) destructor in IViewer. "Interfaces" in C++ are not really interfaces, it's only by convention that you create a class with all pure-virtual methods and no fields: however, they're still just "regular" classes from the compiler's point of view, so you still need to provide an implementation of the destructor.
class IViewer
{
public:
IViewer() { }
virtual ~IViewer() { }
virtual void init() = 0;
};
Is it necessary to declare method init() in PlaneViewer interface also , because it is already defined in IView?
You do not have to declare init() in PlaneViewer, but if you don't PlaneViewer will be an abstract class, meaning that you cannot instantiate it.
If you mean to ask if you have to have 'void init();' in the header file for PlaneViewer and in the .cpp file. The answer is yes.
I cannot complie above code ,give error :
PlaneViewer]+0x28): undefined reference to `typeinfo for IViewer' collect2: ld returned 1 exit status
I think either you are not building the same code or your compile command is incorrect.
I stripped out the QT stuff and was able to build your code just fine with g++.
The error means that the IViewer class was not found by the linker.
I get that error if I remove the '=0' part that makes 'IViewer::init()' a pure virtual function. You could also get that error if you uncommented the constructor and/or destructor in IViewer.
Do I have to have implementation for IView in CPP file?
No. C++ does not care if it is in a .cpp file or a .h file. Unlike Java, the C/C++ preprocessor first resolves all the includes and generates one file containing all the code. It then passes this to the C/C++ compiler. You can actually include a .cpp if you want. Not a good idea though.
The typeinfo issue is caused by not having an implementation of a destructor for the IViewer class. Typically compilers will generate internal data structures (eg. "typeinfo") along with the virtual destructor.
You need to compile and link a file that contains:
#include "iviewer.h"
IViewer::~IViewer() { }
It is good practice to have a virtual destructor because this gives the compiler a compilation unit to use RTTI information, and it also allows the delete operator to work correctly when called on a base class pointer.
Others have answer the question on the init() method, but in summary: If you are going to implement it in PlaneViewer, you need to declare it.
Yes, you need to re-declare virtual void init() in the subclass and implement it, because IViewer declares the function to be pure virtual.
See another question for the explanation of your error. It's caused by declaring a virtual function (not pure) and not defining it. It's not apparent from the code you posted, so I suspect you may have stale object files that were not rebuilt (you have commented out IViewer constructor and virtual destructor).
As an additional note, you should provide virtual destructors with empty body for your interfaces.
I've done significant work in both languages and there is a cookie cutter pattern you can usually follow to turn a Java interface into a c++ interface:
// Start with the Java Interface
interface Numeric {
public int toInteger();
public double toDouble();
};
C++ predates Java and doesn't bother defining the special "interface" keyword for pure virtual classes. So you effectively have to do some work that the Java compiler does automatically:
// The equivalent C++ class
class Numeric {
private:
Numeric(const Numeric&);
Numeric& operator=(const Numeric&);
public:
Numeric() {}
virtual ~Numeric() {}
virtual int toInteger() = 0;
virtual double toDouble() = 0;
};
Another good rule to follow in C++ is, whenever you inherit from a base class with pure virtual methods, re-declare them in the derived class even if you leave them as pure virtuals. It doesn't hurt performance and it lets everybody know that the object is only a partial implementation.
Related
I'm working on a simple C++ program and am having a difficult time understanding a compiler error I was getting. The issue was caused by me attempting to create a derived class from a base class. I've posted my code below with the same structure but have changed the names.
BaseClass.h
#ifndef BASECLASS_H
#define BASECLASS_H
class BaseClass {
public:
BaseClass(void);
virtual int method1(void) = 0;
virtual int method2(void) = 0;
virtual float method3(void) = 0;
};
#endif // BASECLASS_H
DerivedClass.h
#ifndef DERIVEDCLASS_H
#define DERIVEDCLASS_H
#include "DerivedClass.h"
class DerivedClass: public BaseClass
{
public:
DerivedClass(void);
};
#endif // DERIVEDCLASS_H
DerivedClass.cpp
#include "DerivedClass.h"
DerivedClass::DerivedClass(void)
{
}
int DerivedClass::method1(void)
{
// TODO
}
int DerivedClass::method2(void)
{
// TODO
}
float DerivedClass::method3(void)
{
// TODO
}
When attempting to compile this, I get the following error for all the virtual methods:
no 'int DerivedClass::methodX()' member function declared in class 'DerivedClass'
As soon as I declare these methods in the 'DerivedClass.h', the errors go away since the compiler is now aware of the methods.
However, I'm confused. Why was it necessary to re-declare the pure virtual functions in DerivedClass.h? When I #include DerivedClass.h, that will automatically include BaseClass.h, thus I assume my DerivedClass.cpp should be fully aware of the methods. Am I doing something incorrect?
It doesn't work this way. You need to declare the methods you're going to define, whether they're overriding a virtual method or not.
This isn't just an unreasonable requirement of the language. Without this you would be unable to define partially virtual class, i.e., you could have BaseSubtype that has common implementation of method1() but requires classes derived from it to implement method2() and method3()
When you declare a method in a derived class, you say to the compiler:
I want to override this method in this class
So if you don't declare a method in the derived class, you say:
I don't want to override this method; derived class's implementation is the same as the one in the base class
In your case, the base class declares them as pure virtual, so in this case it can be paraphrased:
I don't want to implement this method in this class
If you try to define a method but not declare it, you contradict yourself. The compiler detects that (to protect you from your own negligence).
A very non-intuitive reason why overridden virtual methods must be derived in the base class stems from the fact that C++ allows different parts of the class to be placed into different files, into different translation units.
With some other languages (I'm looking in Java's direction), a single class must be placed in a single file. This is not true with C++. It is perfectly legal for a class to have some of its methods declared in one translation unit, and other methods declared in another translation unit, which could be in a file in some different directory altogether.
Each such file gets compiled separately and individually. When compiling one translation, the C++ compiler has no knowledge of any other translation unit, any other file, that might contain other pieces of the same class.
Now let's say that you are allowed to omit an overriden virtual method from the class declaration. This creates an immediate problem: when compiling the class's constructor, it is necessary for the compiler to know whether the class overrides any virtual methods from any of the superclasses, in order to correctly assemble the virtual table dispatch for the class being constructed. Without an explicit declaration, the compiler has no way of knowing whether or not some other translation unit might define an overridden virtual method.
And that's why overridden virtual methods must be explicitly included in the class's declaration. In conclusion: because C++ formally specifies phase 9, the linkage phase, with the actual compilation carried on in earlier phases, overridden methods must be explicitly declared.
you should override all the base class pure virtual functions to be able to instantiate derived class.
you cannot define a base class member function from derived class.
in your example you are trying to define method1 and method2 and method3 which are not members of DerivedClass!! you have to declare them yourself in your derived class. compiler doesn't do it for you.
so your Derivedclass.h will look like:
#ifndef DERIVEDCLASS_H
#define DERIVEDCLASS_H
#include "BaseClass.h"
class DerivedClass: public BaseClass
{
public:
DerivedClass(void);
virtual int method1(void); // not pure function
virtual int method2(void);
virtual float method3(void);
};
#endif // DERIVEDCLASS_H
Is it essential to have a definition for a virtual function?
Consider this sample program below:
#include <iostream>
using namespace std;
class base
{
public:
void virtual virtualfunc();
};
class derived : public base
{
public:
void virtualfunc()
{
cout << "vf in derived class\n";
}
};
int main()
{
derived d;
return 0;
}
This gives the link-error:
In function base::base():: undefined reference to vtable for base
I do not have the definition for the virtual function in base class. Why is this error occurring even though I have not explicitly invoked the virtual function?
The interesting thing which I find is that if I do not instantiate an object of class derived, the link error is no longer there. Why is this? What has instantiation got to do with the above link error?
The ISO C++ Standard specifies that all virtual methods of a class that are not pure-virtual must be defined.
Reference:
C++03 Standard: 10.3 Virtual functions [class.virtual]
A virtual function declared in a class shall be defined, or declared pure (10.4) in that class, or both; but no diagnostic is required (3.2).
So either you should make the function pure virtual or provide a definition for it.
If you are using gcc, You might get some weird errors if you fail to follow this standard specification. The gcc faq doccuments it as well:
The ISO C++ Standard specifies that all virtual methods of a class that are not pure-virtual must be defined, but does not require any diagnostic for violations of this rule [class.virtual]/8. Based on this assumption, GCC will only emit the implicitly defined constructors, the assignment operator, the destructor and the virtual table of a class in the translation unit that defines its first such non-inline method.
Therefore, if you fail to define this particular method, the linker may complain about the lack of definitions for apparently unrelated symbols. Unfortunately, in order to improve this error message, it might be necessary to change the linker, and this can't always be done.
The solution is to ensure that all virtual methods that are not pure are defined. Note that a destructor must be defined even if it is declared pure-virtual [class.dtor]/7.
You need to provide an implementation of a virtual function ( with its default behaviour ) unless you define the function to be "pure virtual".
So your example could be:
class base
{
public:
void virtual virtualfunc() {} //intentionally do nothing;
};
or
class base
{
public:
void virtual virtualfunc()=0; //pure virtual;
};
You either need to provide a definition, or mark it as abstract/pure-vitual.
void virtual virtualfunc() = 0;
In response to the error about the vtable: the virtual command in this case tells c++ to produce a virtual table of the methods in the base class. In this way when you use polymorphism, C++ is able to replace the base class virtual methods with the methods from the derived class with the same name during run time. This error is telling the user that this replacement is not possible. To fix this error, you will either need to implement the method or set it as pure virtual by adding "=0" at the end of the definition.
In response to the edits: The reason you are not getting an error when you instantiate the object as a base class is because the base class does not need to access the virtual table. On the other hand if you actually try to use this method, you should get an error since no implementation exists. In other words even though you can instantiate an object of the base class its not a complete class.
Yes you would need a body, but perhaps what you are referring to is called a pure virtual functions, which would not need a definition in the base class.
The syntax to define those is as follows:
void virtual virtualfunc() = 0;
After reading this article: Using Interfaces in C++
I have decided to use the __interface keyword with a macro that will add virtual destructors as described in the above link.
I was happy that the __interface keyword will cause the compiler to enforce interface rules, but I was disappointed when I took it for a test drive... It turns out that the __interface keyword does not enforce the rule that a method in the interface should not contain a method body.
I can of course add a macro for function methods but I don't want to do this. Does anyone have any other suggestions?
EDIT: portability is a none issue for me because i must compile on both windows and linux so i will use the __interface keyword when i'm on windows and not on linux , that will be in order to enforce the below rules , which can't be enforced via abstract base class:
Can inherit from zero or more base interfaces.
Can only contain public, pure virtual methods.
Cannot contain data members; properties are allowed.
Cannot inherit from a base class.
Cannot contain constructors, destructors, or operators.
Cannot contain static methods.
besides the destructor issue which can be workaround one can see the advantage of using this keyword in windows env of course.
There is no interface keyword in Standard C++ as in Java, What you have in C++ are Abstract Base Classes.
An Abstract Base Class is a class which has atleast one pure virtual function and an object of such a class cannot be created but a pointer or reference to it can be created. Thus it can be used to simulate the behavior of interfaces.
Example of Abstract class as an interface
class Shape
{
public:
virtual void draw()=0;
};
class Rectangle:public Shape
{
public:
void draw()
{
//draw a Rectangle
}
};
int main()
{
Shape *ptr = new Rectangle();
ptr->draw(); //calls draw() of Rectangle class
return 0;
}
Note that:
__interface keyword as a new Microsoft extension to the C++ compiler.
That is non C++ Standard specified and Non portable.
EDIT: This answer was to a question titled "__interface keyword Win c++" and was tagged C++.
__interface is a microsoft specific extension. It's not standard and not portable.
Also, C++ allows for pure virtual method to have function body.
class Base {
virtual void foo () = 0;
};
void Base::foo ()
{ } // ok
It's advisable to explicitly declare virtual destructor in the class body.
I have a class, which inherits from a class with a pure virtual functions.
Now I need to add another class, which doesn't need some method. I got an idea not to implement this method, instead of always throwing an exception when this method is called, like in the next example :
#include <iostream>
class ibase {
public:
virtual void foo() = 0;
virtual void boo() = 0;
};
class base1 : public ibase {
public:
virtual void foo(){ std::cout<<"base1::foo"<<std::endl; }
virtual void boo(){ std::cout<<"base1::boo"<<std::endl; }
};
class base2 : public ibase {
public:
virtual void foo() { std::cout<<"base2::foo"<<std::endl; }
virtual void boo();
};
int main()
{
ibase *inst1 = new base1;
ibase *inst2 = new base2;
inst1->foo();
inst1->boo();
inst2->foo();
}
But when I tried to compile using next compiler options :
g++ dfg.cpp -ansi -pedantic -Wall
this example produced next output (using g++ 4.3.0) :
/tmp/ccv6VUzm.o: In function `base2::base2()':
dfg.cpp:(.text._ZN5base2C1Ev[base2::base2()]+0x16): undefined reference to `vtable for base2'
collect2: ld returned 1 exit status
Can someone explain why the linking fails? The method boo() is not called.
The vtable for base2 is created - you use a base2. The vtable references boo() - so you need to define it.
10.3/8:
A virtual function declared in a class
shall be defined, or declared pure
(10.4) in that class, or both; but no
diagnostic is required (3.2).
The One-Definition Rule states that each function that is used must be defined exactly once. The definition of the term used includes the following line:
a virtual function is used if it is
not pure
That means that all non-pure virtual functions have to be defined even if they aren't called
It fails because the internal vtable needs a place to point to. It doesn't matter if it is called, the vtable is still created.
Create an empty body for the method and you should be good to go.
You have to implement the method in base2, there is no way around it. Polymorphism is a run time behavior, and there is no way for the linker to know that boo will never be called. You can simply provide a dummy implementation in the base class instead of making it pure virtual if its not mandatory to implement the method in derived class.
boo may not be invoked in reality but it is used to construct the v-table for base2.
You have to define what behaviour will happen is someone has a base2 and calls boo() on it (via its base class pointer) even if there is no point in the code where this is actually invoked. It is part of the contract of implementing an ibase.
The design is of course flawed, and if you want a class that allows a foo only there should be an interface for that.
If your particular instance is that a call is a no-op then that IS a behaviour for the class.
You just forgot to implement virtual void base2::boo (). You have to implement it in order to instantiate base2 class. Otherwise you can leave it pure-virtual by not declaring it in base2 class.
It's late at night here and I'm going crazy trying to solve a linker error.
If I have the following abstract interface:
class IArpPacketBuilder
{
public:
IArpPacketBuilder(const DslPortId& aPortId);
virtual ~IArpPacketBuilder();
// Other abstract (pure virtual methods) here...
};
and I instantiate it like this:
class DummyArpPacketBuilder
: public IArpPacketBuilder
{
public:
DummyArpPacketBuilder(const DslPortId& aPortId)
: IArpPacketBuilder(aPortId) {}
~DummyArpPacketBuilder() {}
};
why am I getting the following error when linking?
Unresolved symbol references:
IArpPacketBuilder::IArpPacketBuilder(DslPortId const&):
ppc603_vxworks/_arpPacketQueue.o
IArpPacketBuilder::~IArpPacketBuilder():
ppc603_vxworks/_arpPacketQueue.o
typeinfo for IArpPacketBuilder:
ppc603_vxworks/_arpPacketQueue.o
*** Error code 1
IArpPacketBuilder is an abstract interface, so as long as I define the constructors and destructions in the concrete (derived) interface, I should be fine, no? Well it appears not.
You have only declared the constructor and destructor of IArpPacketBuilder, not defined them. The linker needs the definitions too. Note that C++ has no concept of abstract interface - IArpPacketBuilder is a plain old class which happens to contain some pure virtual methods, thus making its direct instantiation impossible.
So the simplest solution is to provide inline implementations:
class IArpPacketBuilder
{
public:
IArpPacketBuilder(const DslPortId& aPortId) {}
virtual ~IArpPacketBuilder() {}
// Other abstract (pure virtual methods) here...
};
You can also make the destructor pure virtual, but even so, you still need to provide a definition for it, e.g.
class IArpPacketBuilder
{
public:
IArpPacketBuilder(const DslPortId& aPortId) {}
virtual ~IArpPacketBuilder() = 0;
// Other abstract (pure virtual methods) here...
};
IArpPacketBuilder::~IArpPacketBuilder() {}
You need to provide definitions - i.e. code bodies for both the constructor and destructor for the abstract interface class - both functions will be used in your code, even though the class is abstract. An abstract class is not one which is never instantiated - it is one that is never directly instantiated by the user. It will however be instantiated by the compiler, which needs the constructor and destructor to be defined.
try inline them - works for me although don't know if it's good solution