不能被声明为虚函数的C++函数

本文解析了C++中无法将普通函数、构造函数、静态成员函数、内联成员函数及友元函数声明为虚函数的原因,并阐述了顶层函数、构造函数、静态函数、友元函数和内联函数为何不适合实现多态。

转自 : http://blog.youkuaiyun.com/tianshuai11/article/details/7025415           

          常见的不不能声明为虚函数的有:普通函数(非成员函数);静态成员函数;内联成员函数;构造函数;友元函数。

  1、为什么C++不支持普通函数为虚函数?

  普通函数(非成员函数)只能被overload,不能被override,声明为虚函数也没有什么意思,因此编译器会在编译时邦定函数。

  2、为什么C++不支持构造函数为虚函数?

  这个原因很简单,主要是从语义上考虑,所以不支持。因为构造函数本来就是为了明确初始化对象成员才产生的,然而virtual function主要是为了再不完全了解细节的情况下也能正确处理对象。另外,virtual函数是在不同类型的对象产生不同的动作,现在对象还没有产生,如何使用virtual函数来完成你想完成的动作。(这不就是典型的悖论)

  3、为什么C++不支持内联成员函数为虚函数?

  其实很简单,那内联函数就是为了在代码中直接展开,减少函数调用花费的代价,虚函数是为了在继承后对象能够准确的执行自己的动作,这是不可能统一的。(再说了,inline函数在编译时被展开,虚函数在运行时才能动态的邦定函数)

  4、为什么C++不支持静态成员函数为虚函数?

  这也很简单,静态成员函数对于每个类来说只有一份代码,所有的对象都共享这一份代码,他也没有要动态邦定的必要性。

  5、为什么C++不支持友元函数为虚函数?

  因为C++不支持友元函数的继承,对于没有继承特性的函数没有虚函数的说法。

  *********************************************************************

  1、顶层函数:多态的运行期行为体现在虚函数上,虚函数通过继承方式来体现出多态作用,顶层函数不属于成员函数,是不能被继承的。

  2、构造函数:(1)构造函数不能被继承,因而不能声明为virtual函数。

  (2)构造函数一般是用来初始化对象,只有在一个对象生成之后,才能发挥多态的作用,如果将构造函数声明为virtual函数,则表现为在对象还没有生成的情况下就使用了多态机制,因而是行不通的,如下例:

  view plain #include using namespace std;

  class B { public:B() {} virtual void show()

  { cout<<"***"<

  { cout<<"==="<

  int main(void)

  { B *pb;D d; //先生成对象pb=&d;pb->show(); //再体现多态

  pb=new D(); //先调用构造函数pb->show(); //再多态delete pb;return 0;} 3、static函数:不能被继承,只属于该类。

  4、友元函数:友元函数不属于类的成员函数,不能被继承。

  5、inline函数:inline函数和virtual函数有着本质的区别,inline函数是在程序被编译时就展开,在函数调用处用整个函数体去替换,而virtual函数是在运行期才能够确定如何去调用的,因而inline函数体现的是一种编译期机制,virtual函数体现的是一种运行期机制。此外,一切virtual函数都不可能是inline函数。

<think>首先,用户的问题是:“我想查找在C++不能声明虚函数有哪些 请问C++不能声明虚函数有哪些”。这直接要求列出C++不能声明虚函数函数类型。 根据系统级指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式必须使用$$...$$格式并单独成段。 - LaTeX语法必须正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,如[^1]。 用户提供了几个引用: - 引用[1]: 提到构造函数、静态成员函数、友元函数不能声明虚函数。 - 引用[2]: 讨论虚函数签名不匹配的错误。 - 引用[3]: 详细列出了不能声明虚函数函数类型:普通函数(非类成员函数)、构造函数、内联函数、静态成员函数、友元函数,以及不会被继承的基类的析构函数没必要声明虚函数。 - 引用[4]: 解释虚函数表的创建。 - 引用[5]: 简要说明虚函数必须是基类的非静态成员函数。 我需要整合这些引用,提供一个清晰、结构化的回答。回答应该包括: 1. 列出不能声明虚函数函数类型。 2. 对每个类型进行简要解释。 3. 添加引用标识。 4. 生成相关问题。 从引用[3]中,最全面的列表是: - 普通函数(非类成员函数) - 构造函数 - 内联函数 - 静态成员函数 - 友元函数 - 不会被继承的基类的析构函数(虽然不是绝对不能,但没必要) 引用[1][5]也支持这些。 关键点: - **普通函数**:只有类的成员函数才能是虚函数普通函数不能声明虚函数,因为它们不涉及继承多态。 - **构造函数**:不能声明虚函数,因为虚函数依赖于对象的创建(通过虚表指针),而构造函数是用于创建对象的。 - **内联函数**:内联函数在编译时展开,而虚函数在运行时动态绑定,因此不能声明虚函数。 - **静态成员函数**:静态函数属于类,而不属于特定对象,因此不支持多态。 - **友元函数**:友元函数不是类的成员函数,因此不能声明虚函数。 - **析构函数**:可以被声明虚函数(且通常应该被声明虚函数当基类会被继承时),但如果基类不会被继承,则声明虚函数是浪费资源。 回答结构: - 先简要介绍虚函数的概念。 - 然后列出不能声明虚函数函数类型,每个类型附带简短解释。 - 使用引用标识。 - 最后生成相关问题。 生成相关问题: - 基于主题,比如:为什么构造函数不能虚函数虚函数如何工作?等。 最终回答: - 使用中文。 - 结构清晰。 </think> 在C++中,虚函数是实现运行时多态的关键机制,它允许子类重写基类的函数。然而,并非所有函数都可以被声明虚函数。根据C++语言规范常见实践,以下类型的函数**不能声明虚函数**,我将逐一解释原因,并提供代码示例说明。这些内容主要基于站内引用[^1]、[^3][^5]的总结。 ### 不能声明虚函数函数类型 1. **构造函数** 构造函数用于初始化对象,在对象创建过程中执行。虚函数依赖于虚函数表(vtable)虚表指针(vptr),这些是在构造函数初始化阶段设置的。如果构造函数虚函数,会导致“先有鸡还是先有蛋”的矛盾:虚函数调用需要vptr,而vptr又需要在构造函数中初始化。 示例代码: ```cpp class Base { public: // 错误:构造函数不能声明虚函数 virtual Base(); // 编译错误 }; ``` 引用说明:构造函数不能声明虚函数,因为虚表指针的初始化发生在构造函数中[^1]。 2. **静态成员函数** 静态成员函数属于类本身,而不是类的实例。它不依赖于对象的this指针,因此无法实现运行时多态(动态绑定)。虚函数要求基于对象类型动态分派,但静态函数在编译时绑定。 示例代码: ```cpp class Base { public: // 错误:静态成员函数不能虚函数 static virtual void show(); // 编译错误 }; ``` 引用说明:静态成员函数无法动态绑定,不支持多态,因此不能声明虚函数[^1]。 3. **友元函数** 友元函数不是类的成员函数,它只是被授予访问类私有成员的权限。虚函数必须是类的成员函数,因此友元函数不具备被声明虚函数的资格。C++也不支持友元函数的继承。 示例代码: ```cpp class Base { public: // 错误:友元函数不能虚函数 friend virtual void helper(); // 编译错误 }; ``` 引用说明:友元函数不能声明虚函数,因为它不是类的成员函数,且不支持继承。 4. **内联函数** 内联函数在编译时展开,目的是减少函数调用开销。而虚函数需要在运行时通过虚表动态绑定,两者机制冲突。如果内联函数声明虚函数编译器通常会忽略inline关键字,但这不是标准行为。 示例代码: ```cpp class Base { public: // 错误:内联函数不适合声明虚函数 virtual inline void print(); // 可能编译通过,但inline无效且不推荐 }; ``` 引用说明:内联函数在编译时展开,虚函数在运行时绑定,机制不兼容。 5. **普通函数(非成员函数)** 普通函数(即全局函数或命名空间函数)不依附于任何类,因此无法被声明虚函数虚函数必须是类的成员函数,以实现基于继承的多态。 示例代码: ```cpp // 错误:普通函数不能虚函数 virtual void globalFunc(); // 编译错误,只能在类内声明虚函数 ``` 引用说明:只有类的成员函数才能被声明虚函数普通函数只能被重载,不能被重写[^5]。 6. **不会被继承的基类的析构函数(虽非绝对禁止,但没必要)** 析构函数可以被声明虚函数(且当基类会被继承时,通常应该如此),但如果基类不会被继承,声明虚函数会浪费内存(因为虚函数需要额外的虚表指针)。C++默认析构函数不是虚函数,以避免不必要的开销。 示例代码: ```cpp class Base { public: // 不推荐:如果Base不会被继承,虚析构函数浪费资源 virtual ~Base(); // 允许,但不必要 }; ``` 引用说明:虚函数实现需要虚表指针,占用额外内存;对于不会被继承的类,虚析构函数是多余的[^3]。 ### 虚函数的基本要求 - 虚函数必须是类的**非静态成员函数**,且访问权限可以是public或protected[^5]。 - 如果子类重写虚函数函数签名(函数名、参数列表、const属性)必须完全匹配,否则会创建新虚函数而非重写(引用[^2]中的错误示例)。 ### 总结 在C++中,不能声明虚函数的主要包括:构造函数、静态成员函数、友元函数、内联函数普通函数,以及不会被继承的基类的析构函数(虽非语法禁止,但无必要)。理解这些限制有助于避免编译错误设计缺陷,确保多态机制的正确实现[^1][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值