总结 : 关键字“virtual” 的使用场合

本文详细介绍了在C++中使用虚拟关键字实现多态性的技术,包括抽象类的概念和虚拟继承的解决多重继承问题的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


下面内容总结了关键字“virtual”使用的几个场合:

  1. 运用多态性;

多态性:C++继承机制中的一种技术,这种技术在程序运行时能一句其类型确认调用哪个函数的能力;

多态性又称 “迟后联编”,又称“滞后联编”。

使用例子:

 1 #include<iostream.h>
 2 
 3 class Base
 4 {
 5 public:
 6     virtual void fn()               //使用了关键字:virtual;
 7     {
 8         cout<<"In Base class\n";
 9     }
10 };
11 
12 class SubClass:public Base
13 {
14 public:
15     virtual void fn()               //使用了关键字:virtual;
16     {
17         cout<<"In SubClass\n";
18     }
19 };
20 
21 void test(Base& b)
22 {
23     b.fn();
24 }
25 
26 void main()
27 {
28     Base bc;
29     SubClass sc;
30     cout<<"Calling test(bc)\n";
31     test(bc);
32     cout<<"Calling test(sc)\n";
33     test(sc);
34 }

 

  2.  抽象类;

严格说,这个条目从属于上面一条。

使用例子:

1 class Display
2 {
3 public:
4     virtual void init()=0;                    //使用了关键字:virtual;
5     virtual void write(char * pString);
6 };

 

   3.  虚拟继承;

为解决多重继承模糊性问题而引入的虚拟继承技术;

使用例子:

 1 #include<iostream.h>
 2 
 3 class Furniture
 4 {
 5 public:
 6     Furniture(){}
 7     void SetWeight(int i){weight=i;}
 8     int GetWeight(){return weight;}
 9 protected:
10     int weight;
11 };
12 
13 class Bed:virtual public Furniture                //使用了关键字:virtual;
14 {
15 public:
16     Bed(){}
17     void Sleep()
18     {
19         cout<<"Sleeping...\n";
20     }
21 };
22 
23 class Sofa:virtual public Furniture               //使用了关键字:virtual;
24 {
25 public:
26     Sofa(){}
27     void WatchTV()
28     {
29         cout<<"Watching TV.\n";
30     }
31 };
32 
33 class SleeperSofa:public Bed, public Sofa
34 {
35 public:
36     SleeperSofa():Sofa(),Bed(){}
37     void FoldOut()
38     {
39         cout<<"Fold out the sofa.\n";
40     }
41 };
42 
43 void main()
44 {
45     SleeperSofa ss;
46     ss.SetWeight(20);
47     cout<<ss.GetWeight()<<endl;
48 }

 

 

 

 

 

转载于:https://www.cnblogs.com/richard-c-java/p/3289268.html

<think>好的,用户的问题是关于如何在C#或C++中不使用virtual关键字来实现类似的多态功能。我需要先理解用户的需求,然后根据现有的知识来找到合适的解决方案。 首先,用户可能对virtual关键字使用有顾虑,比如性能问题或者设计上的简洁性。他们可能希望找到更灵活或更高效的方法来实现多态。在C#中,virtual用于支持方法重写,而C++中同样使用virtual来实现动态多态。但用户想避开这个关键字,所以需要替代方案。 接下来,我需要回忆相关的编程技术。在C#中,接口(interface)是一个常见的替代方案,因为接口方法默认是抽象的,不需要virtual关键字。通过实现接口,不同的类可以提供不同的实现,这类似于多态。另外,委托(delegate)和事件(event)也可以用来实现类似的功能,通过将方法作为参数传递,动态调用不同的实现。 在C++中,模板编程是一种强大的工具,可以在编译时实现静态多态,比如使用CRTP(Curiously Recurring Template Pattern)。这种方法通过模板继承,允许在基类中调用派生类的方法,而无需虚函数。此外,函数指针或std::function也可以用来在运行时改变行为,虽然这可能不如虚函数直接,但确实避免了virtual关键字。 还需要考虑策略模式和组合模式,这两种设计模式通过将行为委托给其他对象来实现多态,而不是依赖继承。这在C#和C++中都适用,比如在C#中使用接口组合,或在C++使用模板和策略类。 另外,C# 8.0引入了接口的默认实现,这使得接口可以包含方法的具体实现,进一步增强了接口的能力,减少了对抽象类或虚方法的依赖。这可能是一个重要的点,需要提到。 用户提供的引用中提到了C#的接口和C++模板的不同,特别是C++/CLI中需要显式指定类型参数,而C#是隐式的。这可能与模板元编程相关,比如在C++使用模板特化或策略类来替代虚函数。 需要注意的是,用户可能希望了解两种语言的解决方案,所以需要分别针对C#和C++给出不同的方法,并比较它们的优缺点。例如,C#的接口和委托更为直接,而C++的模板和CRTP则提供了编译时的灵活性,但可能增加代码复杂度。 最后,要确保回答结构清晰,分点列出不同的方法,并结合示例代码说明。同时,需要引用用户提供的参考文献,特别是关于接口和模板的部分,以增强回答的可信度。</think>在C#和C++中实现多态功能时,若希望避免使用`virtual`关键字,可以通过以下替代方案实现类似功能: ### 一、C# 替代方案 #### 1. 接口实现 通过接口定义行为规范,不同类实现同一接口来达成多态。这是C#官方推荐的方式: ```csharp interface IShape { double CalculateArea(); } class Circle : IShape { public double Radius { get; set; } public double CalculateArea() => Math.PI * Radius * Radius; } class Rectangle : IShape { public double Width { get; set; } public double Height { get; set; } public double CalculateArea() => Width * Height; } ``` 此方法符合C#完全面向对象的特性[^2],且接口支持多重实现[^3]。 #### 2. 委托与事件 使用委托类型实现回调机制: ```csharp public delegate void LogHandler(string message); class Logger { public LogHandler Log; public void WriteLog(string msg) => Log?.Invoke(msg); } // 使用 var logger = new Logger(); logger.Log = Console.WriteLine; logger.WriteLog("Hello without virtual!"); ``` #### 3. 模式匹配(C# 7.0+) 通过类型检查和模式匹配实现分支逻辑: ```csharp void ProcessShape(object shape) { switch(shape) { case Circle c: Console.WriteLine($"Circle area: {c.CalculateArea()}"); break; case Rectangle r: Console.WriteLine($"Rectangle area: {r.CalculateArea()}"); break; } } ``` ### 二、C++ 替代方案 #### 1. 模板元编程 使用静态多态技术(CRTP模式): ```cpp template <typename T> class Base { public: void Execute() { static_cast<T*>(this)->Implementation(); } }; class Derived : public Base<Derived> { public: void Implementation() { std::cout << "CRTP implementation\n"; } }; ``` 此方法在编译期完成多态解析,效率高于虚函数[^4]。 #### 2. 函数指针/函子 使用函数对象实现策略模式: ```cpp class Processor { public: using Operation = std::function<void()>; Operation op; void Execute() { op(); } }; // 使用 Processor p; p.op = []{ std::cout << "Lambda operation\n"; }; p.Execute(); ``` #### 3. 类型特征检查(C++17) 通过`if constexpr`实现编译期多态: ```cpp template <typename T> void Process(T obj) { if constexpr (std::is_base_of_v<Serializable, T>) { obj.Serialize(); } else { obj.DefaultAction(); } } ``` ### 三、对比分析 | 方法 | 优点 | 缺点 | |---------------------|-------------------------------|------------------------------| | 接口实现 | 支持多重继承,类型安全 | 需要显式实现接口方法 | | 模板元编程 | 零运行时开销 | 代码膨胀,调试困难 | | 委托/函数指针 | 运行时灵活性高 | 类型安全性降低 | | 模式匹配 | 代码直观易读 | 需要维护类型检查分支 | 这些方法在不同场景下各有优劣:接口实现适合定义清晰的行为契约,模板元编程适用于高性能场景,委托/函数指针适合需要动态配置行为的场合。在C#中更推荐使用接口实现,而在C++中模板元编程和策略模式都是常用方案[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值