views:

186

answers:

5

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:

  1. 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) ?

+4  A: 

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.

radman
+1  A: 

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.

Alex B
+1  A: 

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;
};
Dean Harding
+1  A: 

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.

jcoffland
+1  A: 

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.

janm