首页 > 试题广场 >

说一说C++ 中哪些函数不能是虚函数?

[问答题]

说一说C++ 中哪些函数不能是虚函数?

推荐

得分点

普通函数(非成员函数)、构造函数、析构函数、友元函数、静态成员函数、内联成员函数

参考答案

标准回答

C++ 中,普通函数(非成员函数)、构造函数、友元函数、静态成员函数、内联成员函数这些不能是虚函数。

  1. 普通函数(非成员函数)

    普通函数(非成员函数)只能被重载,不能被重写,所以声明为虚函数也没有意义,编译器编译时就会绑定函数地址。

  2. 构造函数

    创建派生类对象时,会调用派生类的构造函数,派生类的构造函数中将会调用基类的一个构造函数,这种顺序不同于继承机制。因此派生类不继承基类的构造函数,所以将构造函数声明为虚函数没有意义。

  3. 友元函数

    友元函数不是类成员,而只有成员函数才能是虚函数。

  4. 静态成员函数

    静态成员函数对于每个类来说只有一份代码,所有的对象都共享这一份代码,没有动态绑定的必要性。静态成员函数属于一个类而非某一对象,没有 this 指针,它无法进行对象的判别。

  5. 内联成员函数

    内联函数在编译时被展开,虚函数在运行时才能动态的绑定函数。

编辑于 2021-09-15 11:23:58 回复(0)
普通函数
普通函数(非成员函数)只能被重载,不能被重写,而且编译器会在编译时绑定函数。
多态的运行期行为体现在虚函数上,虚函数通过继承方式来体现出多态作用,顶层函数不属于成员函数,是不能被继承的
构造函数
因为构造函数本来就是为了明确初始化对象成员才产生的,然而virtual function主要是为了在不完全了解细节的情况下也能正确处理对象。另外,virtual函数是在不同类型的对象产生不同的动作,现在对象还没有产生,如何使用virtual函数来完成你想完成的动作。
内联成员函数
内联函数就是为了在代码中直接展开,减少函数调用花费的代价,虚函数是为了在继承后对象能够准确的执行自己的动作,这是不可能统一的。
静态成员函数
静态成员函数对于每个类来说只有一份代码,所有的对象都共享这一份代码,他也没有要动态邦定的必要性。不能被继承,只属于该类。
友元函数
C++不支持友元函数的继承,对于没有继承特性的函数没有虚函数的说法。友元函数不属于类的成员函数,不能被继承
发表于 2022-04-04 18:43:03 回复(0)
普通函数
普通函数(非成员函数)只能被overload,不能被override,而且编译器会在编译时绑定函数。
多态的运行期行为体现在虚函数上,虚函数通过继承方式来体现出多态作用,顶层函数不属于成员函数,是不能被继承的
构造函数
因为构造函数本来就是为了明确初始化对象成员才产生的,然而virtual function主要是为了在不完全了解细节的情况下也能正确处理对象。另外,virtual函数是在不同类型的对象产生不同的动作,现在对象还没有产生,如何使用virtual函数来完成你想完成的动作。
内联成员函数
内联函数就是为了在代码中直接展开,减少函数调用花费的代价,虚函数是为了在继承后对象能够准确的执行自己的动作,这是不可能统一的。
静态成员函数
静态成员函数对于每个类来说只有一份代码,所有的对象都共享这一份代码,他也没有要动态邦定的必要性。不能被继承,只属于该类。
友元函数
C++不支持友元函数的继承,对于没有继承特性的函数没有虚函数的说法。友元函数不属于类的成员函数,不能被继承。
发表于 2022-01-17 21:06:58 回复(0)

在 C++ 中,以下函数不能是虚函数


1️⃣ 构造函数(Constructor)

❌ 不能是虚函数,因为对象在构造时先调用基类构造函数,此时派生类的vtable还未初始化,无法进行虚函数调用。

class Base {
public:
    virtual Base() {}  // ❌ 错误:构造函数不能是虚函数
};

✅ 解决方案

  • 使用虚析构函数确保正确的析构顺序


2️⃣ 静态成员函数(Static Function)

❌ 不能是虚函数,因为静态函数不属于某个对象,而虚函数需要this指针来实现动态绑定

class Base {
public:
    virtual static void func() {}  // ❌ 错误:静态函数不能是虚函数
};

✅ 解决方案

  • 如果想实现类似的行为,可以用全局函数或者非静态成员函数


3️⃣ 内联函数(Inline Function)

⚠️ 理论上可以是虚函数,但没意义
内联是编译时决定的,虚函数是运行时决定的,二者冲突。

class Base {
public:
    virtual inline void func() {}  // ⚠️ 可以写,但没意义
};
  • 🔹 如果是Base* p = new Derived; p->func();,那么func()不能被内联,因为p的具体类型只有运行时才能确定。


4️⃣ 友元函数(Friend Function)

❌ 不能是虚函数,因为友元函数不是类的成员函数,不能通过this指针访问vtable。

class Base {
public:
    virtual friend void func();  // ❌ 错误:友元函数不能是虚函数
};

✅ 解决方案

  • 友元函数可以在内部调用虚函数,从而间接实现多态。


5️⃣ 运算符重载中operator=(赋值运算符)

❌ 不能是虚函数,因为拷贝赋值运算符不会触发多态,调用的是对象所属的类的赋值运算符

class Base {
public:
    virtual Base& operator=(const Base& other) {  // ❌ 不能是虚函数
        return *this;
    }
};

✅ 解决方案

  • 可以在operator=内部调用虚函数


6️⃣ 模板函数(Template Function)

❌ 不能直接是虚函数,因为模板在编译期展开,而虚函数在运行时调用,二者机制不同。

class Base {
public:
    virtual template <typename T> void func(T t) {}  // ❌ 不能是虚函数
};

✅ 解决方案

  • 模板+虚函数可以结合使用,例如CRTP(Curiously Recurring Template Pattern)。


🔥 总结

函数类型 是否可虚拟化 原因
构造函数 ❌ 不能 vtable还未初始化
静态成员函数 ❌ 不能 无this指针
内联函数 ⚠️ 可以但没意义 内联是编译时,虚函数是运行时
友元函数 ❌ 不能 不是类成员,无this指针
赋值运算符= ❌ 不能 赋值时不涉及多态
模板函数 ❌ 不能 编译期展开,不能用virtual

🚀 重点记忆
析构函数~Base()一定要是virtual,否则派生类对象析构不完全
构造函数、静态函数、友元函数、赋值运算符 不能是虚函数

这就是 C++ 不能是虚函数的函数类型! 🎯

发表于 2025-04-04 17:49:11 回复(0)
模板函数
发表于 2022-03-11 17:28:08 回复(0)
不能被继承和不能被重写的函数。包括普通函数,即非类成员函数,内联函数,静态成员函数(属于类),构造函数,友元函数。
编辑于 2024-03-27 17:35:49 回复(0)

普通函数(非类成员函数)、构造函数、内联函数、友元函数、静态成员函数

发表于 2023-09-14 16:53:24 回复(0)