C++接口的多重继承?

发布于 2024-09-05 05:01:16 字数 1333 浏览 3 评论 0原文

大家好,

我来自 Java 背景,我在多重继承方面遇到困难。

我有一个名为 IView 的接口,它具有 init() 方法。我想派生一个名为 PlaneViewer 的新类,实现上述接口并扩展另一个类。 (QWidget)。

我的实现如下:

IViwer.h(只有头文件,没有CPP文件):

#ifndef IVIEWER_H_
#define IVIEWER_H_

class IViewer
{
public:
  //IViewer();
  ///virtual
  //~IViewer();
  virtual void init()=0;
};

#endif /* IVIEWER_H_ */

我的派生类。

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(){

}

我的问题是:

  1. 是否还需要在 PlaneViewer 接口中声明方法 init() ,因为它已经在 IView 中定义了?

2.我无法遵守上面的代码,给出错误:

PlaneViewer]+0x28):未定义对“IViewer的typeinfo”的引用 collect2:ld返回1退出状态

我是否必须在CPP文件中实现IView(因为我想要的是一个接口,而不是实现)?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

怪异←思 2024-09-12 05:01:16

考虑接口类的一个好方法是它们指定派生类必须实现哪些方法。

是否需要声明方法
PlaneViewer 界面中的 init() 也是如此,
因为它已经定义在
我查看?

简单的回答是,是的,您必须在 IViewer 中实现 init 方法,因为在基类中该方法被声明为纯虚方法。这意味着任何派生类都必须提供该方法自己的实现,因为没有实现基类方法。

2.我无法编译上面的代码,给出错误:

PlaneViewer]+0x28): 未定义
引用“IViewer 的类型信息”
collect2:ld返回1退出状态

这是一个 g++ 编译器错误,表明(如上所述)您有一个来自具有纯虚函数的基类的派生类,并且该派生类没有实现纯虚方法,因为它必须

哦,还应该注意的是,您没有多重继承的问题,如果只涉及 IViewerPlaneViewer ,问题仍然存在。

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.

江城子 2024-09-12 05:01:16

是的,您还必须在 PlaneViewer 中声明 init。如果您不这样做,那么 init 将不会存在于 PlaneViewer 中,并且 PlaneViewer 仍将被视为抽象(因为没有 PlaneViewer 的实现) >初始化)。

您需要在 IViewer 中为(虚拟)析构函数定义空主体。 C++ 中的“接口”并不是真正的接口,只是按照惯例,您创建一个包含所有纯虚拟方法且没有字段的类:但是,从编译器的角度来看,它们仍然只是“常规”类,因此您仍然需要提供析构函数的实现。

class IViewer
{
public:
    IViewer() { }
    virtual ~IViewer() { }

    virtual void init() = 0;
};

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;
};
樱花细雨 2024-09-12 05:01:16

是否还需要在 PlaneViewer 接口中声明方法 init(),因为它已经在 IView 中定义了?

您不必在 PlaneViewer 中声明 init() ,但如果您不声明,PlaneViewer 将是一个抽象类,这意味着您无法实例化它。

如果您想问是否必须有“void init();”在 PlaneViewer 的头文件和 .cpp 文件中。答案是肯定的。

我无法遵守上面的代码,给出错误:
PlaneViewer]+0x28): 对 `typeinfo for IViewer' 的未定义引用collect2: ld 返回 1 退出状态

我认为您要么没有构建相同的代码,要么您的编译命令不正确。

我去掉了 QT 的东西,并且能够使用 g++ 构建你的代码。

该错误意味着链接器未找到 IViewer 类。

如果我删除使“IViewer::init()”成为纯虚函数的“=0”部分,则会出现该错误。如果您在 IViewer 中取消注释构造函数和/或析构函数,也可能会收到该错误。

我必须在 CPP 文件中实现 IView 吗?

不。C++ 不关心它是在 .cpp 文件还是 .h 文件中。与 Java 不同,C/C++ 预处理器首先解析所有包含内容并生成一个包含所有代码的文件。然后它将其传递给 C/C++ 编译器。如果需要,您实际上可以包含 .cpp。但这不是一个好主意。

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.

奈何桥上唱咆哮 2024-09-12 05:01:16

typeinfo 问题是由于没有实现 IViewer 类的析构函数而引起的。通常编译器会生成内部数据结构(例如“typeinfo”)以及虚拟析构函数。

您需要编译并链接一个包含以下内容的文件:

#include "iviewer.h"

IViewer::~IViewer() { }

使用虚拟析构函数是一种很好的做法,因为这为编译器提供了一个使用 RTTI 信息的编译单元,并且还允许在基类指针上调用时删除运算符正确工作。

其他人已经回答了有关 init() 方法的问题,但总而言之:如果要在 PlaneViewer 中实现它,则需要声明它。

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.

李不 2024-09-12 05:01:16

是的,你需要在子类中重新声明virtual void init()并实现它,因为IViewer将函数声明为纯虚函数。

有关错误的解释,请参阅另一个问题。这是由于声明了虚函数(非纯虚函数)而不定义它而引起的。从您发布的代码中看不出来,所以我怀疑您可能有未重建的陈旧对象文件(您已注释掉 IViewer 构造函数和虚拟析构函数)。

作为附加说明,您应该为虚拟析构函数提供空界面的正文

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.

っ〆星空下的拥抱 2024-09-12 05:01:16

我在这两种语言上都做了很多工作,并且您通常可以遵循一种千篇一律的模式将 Java 接口转换为 C++ 接口:

// 从 Java 接口开始

interface Numeric {
   public int     toInteger();
   public double  toDouble();
};

C++ 早于 Java 并且不需要定义特殊的“接口” " 纯虚拟类的关键字。因此,您实际上必须执行 Java 编译器自动执行的一些工作:

// 等效的 C++ 类

class Numeric {
private:
   Numeric(const Numeric&);
   Numeric& operator=(const Numeric&);
public:
   Numeric() {}
   virtual ~Numeric() {}

   virtual int    toInteger() = 0;
   virtual double toDouble() = 0;
};

在 C++ 中要遵循的另一个好规则是,每当您从具有纯虚方法的基类继承时,请在派生类中重新声明它们即使你将它们保留为纯虚拟的。它不会影响性能,并且让每个人都知道该对象只是部分实现。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文