-
2015-05-26 00:48:05
C++中,虚函数可以为private,并且可以被子类覆盖。
例如,下面程序工作正常。
#include<iostream> class Base { private: virtual void fun() { std::cout << "Base Fun" << std::endl; } friend int main(); }; class Derived : public Base { public: void fun() { std::cout << "Derived Fun" << std::endl; } }; int main() { Base* ptr = new Derived; ptr->fun(); return 0; }
运行结果:
Derived fun()对于上面的程序,有下面几点是需要注意的方面:
1) ptr是一个Base类型的指针,指向的是Derived对象。最终实际调用的是Derived::fun()。2) int main()是Base类的友元函数。如果删除这个友元声明,则程序会编译失败。因为在编译期间,会进行权限检查。对于这行代码ptr->fun(), 编译器会检查到fun是私有函数,base类型的对象/指针无权访问。
这种行为与Java完全不同。在Java中,私有方法默认是final的,不能被覆盖。
更多相关内容 -
C++中虚函数能不能声明为private
2019-07-13 22:11:12如果声明虚函数声明为private时编译会报错,但是还是有手段调用声明为private的虚函数的。首先让我们来看看调用声明为private的虚函数时会发生什么情况。 #include <iostream> using namespace std; class ...如果声明虚函数声明为private时编译会报错,但是还是有手段调用声明为private的虚函数的。首先让我们来看看调用声明为private的虚函数时会发生什么情况。
#include <iostream> using namespace std; class classB { private: virtual void fun() { cout << "virtual fun of classB" << endl; } void fun2() { cout << "fun2 of classB" << endl; } //friend int main(); }; class classA : public classB { public: virtual void fun() { cout << "virtual fun of classA" << endl; } void fun2() { cout << "fun2 of classA" << endl; } }; int main() { classB *obj = new classA; obj->fun(); obj->fun2(); while (1); return 0; }
那么如何能把虚函数声明为private呢,把要调用该虚函数的函数声明为类的友元函数就行了,让我们看一下。
#include <iostream> using namespace std; class classB { private: virtual void fun() { cout << "virtual fun of classB" << endl; } void fun2() { cout << "fun2 of classB" << endl; } friend int main(); }; class classA : public classB { public: virtual void fun() { cout << "virtual fun of classA" << endl; } void fun2() { cout << "fun2 of classA" << endl; } }; int main() { classB *obj = new classA; obj->fun(); obj->fun2(); while (1); return 0; }
可以看到当classA中的虚函数为public是可以这样调用的,但是如果classA中的虚函数声明为private还可以调用吗?让我们来看一下。
#include <iostream> using namespace std; class classB { private: virtual void fun() { cout << "virtual fun of classB" << endl; } void fun2() { cout << "fun2 of classB" << endl; } friend int main(); }; class classA : public classB { public: void fun2() { cout << "fun2 of classA" << endl; } private: virtual void fun() { cout << "virtual fun of classA" << endl; } }; int main() { classB *obj = new classA; obj->fun(); obj->fun2(); while (1); return 0; }
可以看到即使classA中的虚函数声明为private时还是可以调用的,这是为什么呢?main又不是classA的友元函数,我个人观点是虚函数是实际上通过classB对象来调用的,如果理解有错麻烦告诉我一下,谢谢!
-
详解C++中如何将构造函数或析构函数的访问权限定为private
2021-01-01 04:27:59当我们在程序中声明一个对象时,编译器为调用构造函数(如果有的话),而这个调用将通常是外部的,也就是说它不属于class对象本身的调用,假如构造函数是私有的,由于在class外部不允许访问私有成员,所以这将导致... -
C++之private虚函数
2018-09-16 23:40:04一般我们说虚函数,它的访问级别都是public的,用类对象可以直接调用,这样就可以实现运行时的类型绑定,那如果我们将虚函数私有化会出现什么情况呢? 我们先来看一个非虚函数私有化的例子 class Base { private:...一般我们说虚函数,它的访问级别都是public的,用类对象可以直接调用,这样就可以实现运行时的类型绑定,那如果我们将虚函数私有化会出现什么情况呢?
我们先来看一个非虚函数私有化的例子
class Base { private: void PrintClassName () { cout<<"Base"<<endl; } public: void print() { PrintClassName(); } }; class Derived : public Base { private: void PrintClassName() { cout<<"Derived"<<endl; } };
在main函数里产生一个Derived的对象d,然后调用print()函数,即d.print(),结果输出的却是Base,print()函数没有调用子类的PrintClassName函数,而是调用父类的PrintClassName函数,原来是由于PrintClassName函数不是虚函数之故,所以Base的print()函数调用PrintClassName()函数是在编译时就已经绑定了,而不是运行期绑定。
下面我们让PrintClassName()函数变成虚函数再执行,就可以看到输出的类名为子类的名称,即Derived。
那么我们有没有办法调用私有的虚函数呢?当然是有的,不管公有还是私有,只要是虚函数,它的函数地址都会放在虚函数表vftable中,只要我们找到虚函数表中存放的PrintClassName()函数的地址,我们就可以直接调用,前提是你必须对C++类对象的内存布局要熟悉,代码如下,这样也输出Derived,与前面效果相同
int _tmain(int argc, _TCHAR* argv[]) { Derived d; //d.print(); typedef void (*Fun)(); Fun pFun = NULL; pFun = (Fun)*((int *)(*(int *)&d + 0) + 0); pFun(); getchar(); return 0; }
-
调用private/protected修饰的虚函数
2019-08-04 15:16:31前些天面试,被问到一个很有意思的问题:c++中能否调用protected修饰的虚函数,之前没有尝试过,所以只能靠直觉回答:“在技术上,只要知道虚函数表的地址就可以调用,但是不清楚protected保护的机制是具体在哪...
本文目的
前些天面试,被问到一个很有意思的问题:c++中能否直接调用protected修饰的虚函数,之前没有尝试过,所以只能靠直觉回答:“在技术上,只要知道虚函数表的地址就可以调用,但是不清楚protected保护的机制是具体在哪一个时期起的作用,可能需要一些手段来绕开这个机制。” 我的回答就是这样(自我感觉回答的还是含糊不清楚,只是概念上推测,没有给出具体的方法)。好心的面试官还是跟我解释了protected是编译器在编译期做检查。所以本文就直接上代码,给出解决此问题的具体的实现。
(ps:对虚函数表内部结构不明白的可以看我的另一篇文章,C++在gcc下的单继承,多继承,虚继承的内存布局)
代码
不可行的直接调用
1 #include<iostream> 2 3 using namespace std; 4 5 typedef void (*Fuc)(void); 6 7 class A{ 8 protected: 9 virtual void foo() 10 { 11 cout<<"A foo"<<endl; 12 } 13 private: 14 virtual void bar() 15 { 16 cout<<"A bar"<<endl; 17 } 18 }; 19 20 int main() 21 { 22 A* a = new A; 23 a->foo(); 24 a->bar(); 25 }
结果:
意料之内的编译错误。
可行的指针调用
1 #include<iostream> 2 3 using namespace std; 4 5 typedef void (*Fuc)(void); 6 7 class A{ 8 protected: 9 virtual void foo() 10 { 11 cout<<"A foo"<<endl; 12 } 13 private: 14 virtual void bar() 15 { 16 cout<<"A bar"<<endl; 17 } 18 }; 19 20 int main() 21 { 22 A* a = new A; 23 Fuc fucFoo = (Fuc)*((long*)*(long*)a); 24 Fuc fucBar = (Fuc)*((long*)*(long*)a+1); 25 fucFoo(); 26 fucBar(); 27 }
运行结果:
成功运行,且没有触发编译器的检查(因为就没有调用A的对象,单纯根据虚函数地址通过函数指针调用)。
(ps:对虚函数表内部结构不明白的可以看我的另一篇文章,C++在gcc下的单继承,多继承,虚继承的内存布局)
尾语
不明白就得动手,不然只能原地打转,处于被动。
以上
-
C++如何处理内联虚函数
2021-01-20 03:37:06当一个函数是内联和虚函数时,会发生代码替换或使用虚表调用吗? 为了弄清楚内联和虚函数,让我们将它们分开来考虑。通常,一个内联函数是被展开的。 class CFoo { private: int val; public: int GetVal... -
虚函数用作private会怎样?
2017-09-04 22:31:592.如果使用指向对象的引用或指针来调用虚函数,程序将使用为对象类型定义的方法,而不是使用为引用或指针类型定义的方法。这样基类引用或指针就可以指向派生类对象。3.如果定义的类将被用作基类,则应将那些要在派生... -
c++的虚函数如果是private的,该如何实现多态
2019-06-27 10:36:25关于虚函数的回顾: 1) :虚函数的地址存放于虚函数表之中。... 3):虚函数的调用会被编译器转换为对虚函数表的访问 。 当虚函数是public的,这个时候实现多态的方式: class Base { public: virtual... -
c++中虚函数和纯虚函数的作用与区别
2020-12-31 07:55:04虚函数为了重载和多态的需要,在基类中是有定义的,即便定义是空,所以子类中可以重写也可以不写基类中的此函数! 纯虚函数在基类中是没有定义的,必须在子类中加以实现,很像java中的接口函数! 虚函数 引入原因:... -
纯虚函数设置为public、protected和private的区别
2020-05-05 18:42:58我们把一个仅仅含有纯虚函数的类...那么,让我们想一想,纯虚函数或者虚函数可以为private吗?如果这种方式是可行的,那么什么时候可以将(纯)虚函数设为private了?这些都是本文将要讨论的主题。一起来看看。 一.... -
private的虚函数
2012-05-14 15:13:30我们把一个仅仅含有纯虚函数的类称为接口...那么,让我们想一想,纯虚函数或者虚函数可以为private吗?如果这种方式是可行的,那么什么时候可以将(纯)虚函数设为private了?这些都是本文将要讨论的主题。一起来看看。 -
为什么基类指针(或引用)可以调用派生类的private虚函数
2017-07-18 14:25:38在基类中定义了public虚函数,在派生类中将其重写,但是设置为private,为什么通过基类指针仍然可以发生动态绑定调用派生类中的private虚函数? 例子如下: class Base { public: // public虚函数 virtual void ... -
利用虚函数让private外部访问成为可能!
2009-03-12 18:46:30同上利用虚函数让private外部访问成为可能!.。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 -
纯虚函数能为private吗?
2012-11-24 10:51:38我们把一个仅仅含有纯虚函数的类称为接口...那么,让我们想一想,纯虚函数或者虚函数可以为private吗?如果这种方式是可行的,那么什么时候可以将(纯)虚函数设为private了?这些都是本文将要讨论的主题。一起来看看。 -
虚函数与private
2013-09-04 02:05:37我们把一个仅仅含有纯虚函数的类称为...那么,让我们想一想,纯虚函数或者虚函数可以为private吗?如果这种方式是可行的,那么什么时候可以将(纯)虚函数设为private了?这些都是本文将要讨论的主题。一起来看看。 一 -
C++ 虚函数详解
2021-12-27 20:43:38这里写目录标题概述类的虚表一般继承(无虚函数覆盖)一般继承(有虚函数覆盖)多重继承(无虚函数覆盖)多重继承(有虚函数覆盖)虚表指针动态绑定 概述 C++中的虚函数的作用主要是实现了多态的机制。关于多态,... -
虚函数指针 虚函数表
2020-02-04 14:02:42只有用virtual声明类的成员函数,称之为虚函数。 2.虚函数的作用 就是一句话:实现多态的基石 实现多态的三大步: 1.存在继承关系 子类继承父类 2.子类重写父类的virtual function 3.子类以父类的指针或者是引用的... -
C++、类继承与虚函数
2022-04-11 10:07:50类继承与虚函数的一些基本概念。 -
虚函数的缺陷-子类可以继承父类的私有虚函数但是只能访问父类的public变量
2021-03-07 15:59:37子类可以继承父类的私有虚函数-因为只是方法不是变量 子类 class WeatherBase { private: virtual void init(); } class Rain : public WeatherBase { private: virtual void init(); } 一个成员函数被定义... -
c#中虚函数的相关使用方法
2021-01-20 06:50:08我们知道一般函数在编译时就静态地编译到了执行文件中,其相对地址在程序运行期间是不发生变化的,而虚函数在编译期间是不被静态编译的,它的相对地址是不确定的,它会根据运行时期对象实例来动态判断要调用的函数,... -
C++ private继承的意义与虚函数表
2018-02-05 07:52:43用effective C++中的话说就是private继承是实现继承。...这时可以用private继承。或者Base和Derivative根本没有任何逻辑上的联系,单纯的D想要复用一下B的代码,这时就用private 继承。 在一个对象的内存空间中有 -
纯虚函数能为private吗
2013-11-19 08:28:01我们把一个仅仅含有纯虚函数的类称为接口...那么,让我们想一想,纯虚函数或者虚函数可以为private吗?如果这种方式是可行的, 那么什么时候可以将(纯)虚函数设为private了?这些都是本文将要讨论的主题。一起来看看 -
虚函数详解
2019-03-09 20:05:26文章目录一、虚函数实例二、虚函数的实现(内存布局)1、无继承情况2、单继承情况(无虚函数覆盖)3、单继承情况(有虚函数覆盖)4、多重继承...问题1、构造函数为什么不能定义为虚函数2、析构函数为什么要定义为虚函数... -
C++中虚继承产生的虚基类指针和虚基类表,虚函数产生的虚函数指针和虚函数表
2021-10-19 22:50:16本博客主要通过查看类的内容的变化,深入探讨有关虚指针和虚表的问题。 一、虚继承产生的虚基类表指针和虚基类表 ...private: int c; }; class Son1 :virtual public Base { public: int a; protected: i -
C 中的虚函数(virtual function)
2021-05-23 09:37:39简介虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。假设我们有下面的类层次:class Father{public:virtual void foo() { cout << "Father::foo() is called"<... -
C++虚函数详解
2021-05-26 10:25:431.虚函数的使用? 1.1虚函数的定义 在实现c++多态时会用到虚函数。虚函数使用的其核心目的是通过基类访问派生类定义的函数。...上述代码在基类中定义了一个test的虚函数,所有可以在其子类重新定义父 -
关于类的虚函数的public,private的继承问题。
2015-12-24 15:02:02下面的代码编译结果报错。 test.c: In function `int main(int, char**)': test.c:18:22: error: `virtual void TEST2::testxiongyf()' is private test.c:60:25: error: within this ...如果把private切换为public, -
友元函数&虚函数
2018-03-21 09:34:50被友元的虚函数,是可以被继承的三个类Myclass,Myclass2,son,Myclass对Myclass2的set函数友元,son继承Myclass2,如果son不重写set函数,而是直接继承Myclass2的set,是可以操作Myclass私有属性的。#include &... -
C++ 多态与虚函数
2022-03-24 17:15:50多态性与虚函数多态性虚函数 多态性 多态性是面向对象程序设计的关键技术之一,若程序设计语言不支持多态性,不能称为面向对象的语言,利用多态性技术,可以调用同一个函数名的函数,实现完全不同的功能 在C++中有两...