常见的不不能声明为虚函数

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#include <iostream>

using namespace std;

 

class B

{

public:

       B(){}

       virtualvoid show()

       {

              cout<<"***"<<endl;

       }

};

class D:public B

{

public:

       D(){}

       voidshow()

       {

              cout<<"==="<<endl;

       }

};

 

int main(void)

{

       B*pb;

       Dd;        //先生成对象

       pb=&d;

       pb->show();//再体现多态

 

       pb=newD(); //先调用构造函数

       pb->show();//再多态

       deletepb;

       return0;

}

 

3static函数:不能被继承,只属于该类。

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

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

### C++ 虚函数与模板函数的结合:使用场景及限制 在 C++ 中,虚函数和模板函数是两种强大的工具,分别支持动态多态性和静态多态性。然而,由于它们的工作原理同,将两者结合起来可能会带来一些挑战和限制。 --- #### 虚函数的作用 虚函数的主要作用是在运行时决定调用哪个函数版本(即实现运行时多态)。当通过基类指针或引用调用虚函数时,实际被调用的是派生类中覆盖的版本[^1]。 #### 模板函数的作用 模板函数允许编译器根据传入参数的类型生成特定的函数实例(即实现编译时多态)。它依赖于继承关系,而是基于通用代码的一次编写、多次应用的思想[^2]。 --- ### 结合虚函数与模板函数的可能性 尽管虚函数和模板函数都涉及多态的概念,但由于其本质差异,直接结合二者并非易事。主要原因在于: - **虚函数**需要在运行时解析具体调用的目标。 - **模板函数**则完全由编译期处理完成。 因此,在大多数情况下,C++ 允许直接声明一个既是虚函数又是模板函数的方法。过,有一些间接方式可以模拟这种行为。 --- #### 方法一:利用模板类配合虚函数 可以通过定义一个带有模板参数的基类,并在其内部包含虚函数来达到目的。例如: ```cpp template<typename T> class Base { public: virtual void process(T value) = 0; // 声明虚函数 virtual ~Base() {} }; // 派生类显式指定模板参数 class DerivedInt : public Base<int> { public: void process(int value) override { std::cout << "Processing int: " << value << '\n'; } }; class DerivedDouble : public Base<double> { public: void process(double value) override { std::cout << "Processing double: " << value << '\n'; } }; ``` 在这种设计中,`process()` 函数既具有虚函数的特点又能够适应同类型的数据输入[^3]。 --- #### 方法二:工厂模式加策略模式 另一种常见做法是采用工厂模式创建适当类型的对象,再结合策略模式执行所需的操作。这实际上是一种更高层次上的解耦方案。 示例代码如下所示: ```cpp #include <iostream> #include <memory> using namespace std; struct StrategyInterface { template<typename T> virtual void execute(const T& data) = 0; virtual ~StrategyInterface() {}; }; template<typename T> struct ConcreteStrategy : public StrategyInterface { void execute(const T& data) override { cout << "Executing with type: " << typeid(data).name() << endl; } }; unique_ptr<StrategyInterface> create_strategy_for_type(bool is_int) { if(is_int){ return make_unique<ConcreteStrategy<int>>(); }else{ return make_unique<ConcreteStrategy<string>>(); } } int main(){ auto strategyA = create_strategy_for_type(true); strategyA->execute(42); auto strategyB = create_strategy_for_type(false); strategyB->execute(string{"Hello"}); } ``` 此方法巧妙地绕过了直接混合虚函数和模板的技术障碍,同时保留了两者的优点[^4]。 --- ### 使用场景分析 1. **跨平台框架开发** - 在某些大型项目中可能遇到多种数据源需统一接口的情况,此时上述技术尤为适用。 2. **插件系统构建** - 插件往往需要灵活适配各种未知格式的数据流,而会牺牲性能或增加复杂度太多。 3. **高性能计算库** - 对数值密集型运算而言,提前确定操作数类型至关重要;但与此同时也要保持足够的扩展能力应对未来需求变化。 --- ### 局限性探讨 即使有了以上解决方案,仍然存在若干固有限制值得注意: - 编译时间增长:因为每次新增一种新类型都会触发额外一轮编译流程; - 可读性降低:对于初学者来说理解这类高级技巧有一定难度; - 运行效率折衷:虽然理论上避免了必要的转换开销,但实际上仍可能存在隐含成本。 综上所述,合理权衡利弊之后谨慎选用才是明智之举。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值