关于C++:如何从派生类函数调用父类函数? |
您所在的位置:网站首页 › es6子类调用父类函数 › 关于C++:如何从派生类函数调用父类函数? |
如何调用C++派生类中的父函数?例如,我有一个名为parent的类,还有一个名为child的类,它是从父类派生的。内每个类都有一个print函数。在定义孩子的打印函数时,我想调用家长的打印函数。我该怎么做呢? 相关讨论 所有上述解决方案都假定您的打印功能是一种静态的方法。这是案子吗?如果方法不是静态的,那么以上的解决方案就不相关。 HAFEZ,you are mistaken the base:function()syntax looks like static method call syntax,but it works for instance methods in this context. 我不会用MSVC的,因为它是特殊的平台。虽然你的代码可能不在其他平台上运行,但我会利用其他的建议 如果我超负荷的话,我可以叫一个基本班的虚拟功能吗? 来自阶级的反模式总是需要召唤家长阶级函数,称为超级我将冒风险说明明显的问题:如果函数是在基类中定义的,那么它将自动在派生类中可用(除非它是private)。 如果派生类中有一个具有相同签名的函数,则可以通过添加基类的名称后跟两个冒号base_class::foo(...)来消除它的歧义。您应该注意到,与Java和C语言不同,C++没有"基类"(EDOCX1 8或EDCOX1 3)的关键字,因为C++支持多重继承,这可能导致歧义。 123456789101112131415161718192021222324class left { public: void foo(); }; class right { public: void foo(); }; class bottom : public left, public right { public: void foo() { //base::foo();// ambiguous left::foo(); right::foo(); // and when foo() is not called for 'this': bottom b; b.left::foo(); // calls b.foo() from 'left' b.right::foo(); // call b.foo() from 'right' } };顺便说一句,不能直接从同一个类派生两次,因为没有办法引用其中一个基类。 12class bottom : public left, public left { // Illegal }; 相关讨论 为什么要两次从同一类继承? @bluesm:在经典的OOP中,这没有多大意义,但是在通用编程中,template class C: public A, public B {};可以有两种类型是相同的,这是因为根据代码的使用方式(使a和b是相同的),可能是两个或三个抽象层,来自不知道自己做了什么的人。 我认为添加这个方法很有用,即使它不是直接在父类中实现,而是在继承链中的某个父类中实现,也会调用父类方法。 如果父方法使用这个呢? @martinkunev,如果基类使用它,那么它通常用于常规方法,并禁止对virtual方法进行动态调用。 另一方面,当我试图把这个放进cpp文件时,它让我很生气。我有"使用名称空间标准"。在该命名空间的某个位置定义了Left。这个例子无法编译——让我抓狂了:)。然后我把"左"改为"左"。顺便说一下,很好的例子。 @马太,这就是为什么你不应该使用using namespace std。 +1用于说明You should note that unlike Java and C#, C++ does not have a keyword for"the base class"。 如果你愿意的话,你可以在课堂上加上typedef left super;,然后你可以参考super::foo();。由于不能直接从同一类派生两次,因此必须间接地从ecx1(18)派生,但最好使用组合而不是继承。 如果foo在两个基类中都是虚函数,会发生什么?考虑到名为Parent的父类和名为Child的子类,可以这样做: 1234567891011121314151617class Parent { public: virtual void print(int x); } class Child : public Parent { void print(int x) override; } void Parent::print(int x) { // some default behavior } void Child::print(int x) { // use Parent's print method; implicitly passes 'this' to Parent::print Parent::print(x); }注意,Parent是类的实际名称,而不是关键字。 相关讨论 当然,只有当基调用与其他逻辑穿插时,这才有用,否则就没有必要重写函数,所以可能有点太离题了;) @实际上,它很有用,即使基调用没有与其他逻辑穿插在一起。假设父类几乎可以做任何你想做的事情,但是公开了一个你不想让子类用户使用的方法foo(),要么因为foo()在子类中毫无意义,要么子类的外部调用程序会破坏子类所做的事情。因此,子级可以在某些情况下使用parent::foo(),但提供foo的实现,以便隐藏父级的foo()以避免被调用。 @我是说我听起来很有趣,但是对不起,我还没领会。这里的foo()类似于print()还是一个单独的函数?你的意思是使用private继承来隐藏从基础继承的细节,并为你想要公开的东西提供public隐藏功能? @强调是的,foo()与print()相似。让我回到使用print(),因为我认为在这种情况下它更有意义。假设有人创建了一个类,该类对特定数据类型执行了一些操作,暴露了一些访问器,并有一个print(obj&)方法。我需要一个在array-of-obj上工作的新类,但是其他的都是一样的。组合会导致大量重复的代码。继承最小化了这一点,在print(array-of-obj&)循环中调用print(obj&),但不希望客户调用print(obj&),因为这样做不合理。 @强调这是基于这样一个假设:我不能重构原始父类的公共部分,或者这样做的代价是难以置信的。私有继承可以工作,但随后会丢失所依赖的公共访问器,因此需要复制代码。如果您的基类被称为Base,而您的函数被称为FooBar(),则可以直接使用Base::FooBar()调用它。 12345678910void Base::FooBar() { printf("in Base "); } void ChildOfBase::FooBar() { Base::FooBar(); }在MSVC中有一个特定于Microsoft的关键字: MSDN:允许显式声明正在为要重写的函数调用基类实现。 123456789101112131415161718// deriv_super.cpp // compile with: /c struct B1 { void mf(int) {} }; struct B2 { void mf(short) {} void mf(char) {} }; struct D : B1, B2 { void mf(short) { __super::mf(1); // Calls B1::mf(int) __super::mf('s'); // Calls B2::mf(char) } }; 相关讨论 如果函数也是虚拟的,这就可以工作。漂亮的小费。 嗯,我更喜欢以东x1〔19〕把父母当作以东x1〔20〕那样。 我不会试图证明使用__super的合理性;我在这里提到它是一个替代建议。开发人员应该了解他们的编译器并了解其功能的优缺点。 我宁愿阻止任何人使用它,因为它严重阻碍了代码的可移植性。 我不同意安德烈的观点:如果我们考虑编写主要与编译器无关的软件,开发人员应该了解标准,不必费心于编译器功能,我认为这无论如何都是一个好主意,因为在大型项目中迟早会使用多个编译器。 "ToMaseTestI我都不喜欢,因为C++不是Java,记住父的名字并不难,加上使用MI是必需的。 "开发人员应该知道他们的编译器"这一推理,以及包含非标准特性,正是导致IE6的原因… 这是一个非常糟糕的主意,总是尽量避免使用编译器特定的特性,或者是真正需要的特性,在定义中使用它们,您可以在其中处理标准和非标准方法。 我将反对这些评论,投票支持__super。这很好,也很简单,对于99.9%的代码来说,它是健全的,不使用多重继承,没有问题。多年来,显式地指定基类导致代码库中出现了多个难以诊断的可怕错误,人们最终意外地直接从级别3->级别1开始,跳过中间的级别2类;uu super阻止了这一点。还有可移植代码,这是一个很好的观点,但是并非所有代码都关心可移植性。 @ORIONEDWARDS的代码只有一个继承__super没有添加功能,因为您可以显式地命名该类(或者如果您想写super的话,可以在类声明后立即执行typedef Parent super的习惯):它的主要目的是当一个方法可以是一个或另一个(即,混合场景)。如果您明确需要这种功能,而不是懒散,那么牺牲标准遵从性可能是合理的。 @Orionedwards,好吧,总是从Level3调用Level2方法,你会没事的。如果基类成员函数的访问修饰符是保护的或公共的,则可以从派生类调用基类的成员函数。可以从派生成员函数调用基类非虚拟成员函数和虚拟成员函数。请参考程序。 123456789101112131415161718192021222324252627282930313233343536373839404142434445#include using namespace std; class Parent { protected: virtual void fun(int i) { cout |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |