在C++中模拟Java中final对虚函数的使用

       有时候要求一个类的虚函数成员不再被它的继承类重写,类似于java的final的作用,可以使用如下策略:

class Timer
{
public:
	virtual void onTick() const;
};

class Widget
{
public:

private:
	class WidgetTimer : public Timer
	{
	public:
		virtual void onTick() const;
	};
    WidgetTimer timer;
};

        在Widget类中定义了一个新的WIdgetTimer类,它public继承了Timer类,因此可以重写Timer的虚函数。WidgetTimer的对象是Widget的私有成员变量,因此在它的派生类中是不能访问该私有成员变量的,也就不能重写该虚函数。

        如果Widget是private继承的Timer类,则它的public派生类还是可以重写该虚函数的。

#include <iostream>

using namespace std;

class Timer
{
public:
	virtual void onTick() const
	{
		cout<<"Timer::onTick"<<endl;
	}
};

class Widget : private Timer
{
public:
    void fun()
	{
		onTick();
	}
private:
	virtual void onTick() const
	{
		cout<<"Widget::onTick"<<endl;
	}

};

class Derived : public Widget
{
public:

private:
	virtual void onTick() const
	{
		cout<<"Derived::onTick"<<endl;
	}
};


int main()
{

	Widget *pw;
	Widget w;
	pw = &w;
	pw->fun();


	Derived d;
	pw = &d;
	pw->fun();

	return 0;
}

运行结果:


 

 

 


 

<think>好的,我现在需要帮用户比较C++Java中的继承与多态,并用C++语法演示实现。首先,用户已经学过Java,所以应该从Java的角度出发,对比C++的不同之处。 用户可能想了解的主要区别可能包括语法结构、访问控制、多态的实现机制等。比如,Java所有类默认继承Object,而C++没有;Java使用extends和implements,而C++用冒号和访问修饰符;Java的方法默认虚函数,而C++需要显式声明virtual,并且需要手动使用override。 接下来要考虑用户可能的疑惑点,比如C++中的多重继承,这在Java中是没有的。还有虚函数表和动态绑定的区别,以及C++中的析构函数需要声明为virtual,而Java的垃圾回收机制不同。 然后,我需要组织内容结构,先讲继承,再讲多态。每个部分先说明C++的特点,再对比Java,然后给出代码示例。比如,在继承部分,可以展示C++如何定义基类和派生类,访问修饰符的影响,构造函数的调用顺序等。多态部分则重点讲虚函数、override关键字,以及纯虚函数和抽象类的实现。 还需要注意用户提到的语法演示,确保代码正确且符合C++标准。例如,展示基类Animal和派生类Dog,演示虚函数使用,以及如何通过基类指针调用派生类方法。同时,要提到C++11引入的override关键字,避免拼写错误导致的隐藏问题。 另外,用户可能对内存管理有疑问,比如C++中需要手动管理内存,而Java自动垃圾回收。但这个问题可能不在当前范围内,不过还是可以稍微提及,特别是在多态中,如果使用new创建对象,需要delete释放,而虚析构函数的重要性。 最后,总结关键点,帮助用户记忆。确保对比清晰,代码示例简洁明了,覆盖主要区别和注意事项。检查是否有遗漏的重要点,比如C++支持私有和保护继承,而Java只有公有继承,这也是一个显著的区别。</think>### C++ 继承与多态 vs Java:核心差异与实现详解 以下是 C++Java继承和多态上的主要区别,结合代码示例说明: --- #### 一、**继承的差异** | **特性** | **C++** | **Java** | |-------------------|------------------------------------|------------------------------------| | 默认基类 | 无默认基类 | 所有类隐式继承 `Object` 类 | | 继承语法 | `class 子类 : 访问修饰符 父类` | `class 子类 extends 父类` | | 多重继承 | 支持(可能引发菱形继承问题) | 不支持(通过接口间接实现) | | 访问控制 | `public/protected/private` 继承 | 仅 `public` 继承 | ##### **C++ 继承示例** ```cpp // 基类 class Animal { public: Animal() {} // 构造函数 void eat() { std::cout << "Animal eating" << std::endl; } protected: int age; // 子类可访问 private: int id; // 子类不可访问 }; // 公有继承(保持基类访问权限) class Dog : public Animal { public: void bark() { eat(); // 可访问基类 public 方法 age = 3; // 可访问基类 protected 成员 // id = 1; // 错误:private 成员不可访问 } }; ``` --- #### 二、**多态的差异** | **特性** | **C++** | **Java** | |-------------------|------------------------------------|------------------------------------| | 虚函数 | 需显式声明 `virtual` | 默认所有方法可重写(非 final) | | 动态绑定 | 通过虚函数表实现 | 通过 JVM 方法表实现 | | 抽象类 | 含纯虚函数(`virtual func() = 0;`)| 含抽象方法(`abstract void func();`)| | 接口 | 无接口,用纯虚类模拟 | 通过 `interface` 明确支持 | ##### **C++ 多态示例** ```cpp // 基类定义虚函数 class Shape { public: virtual void draw() { std::cout << "Drawing shape" << std::endl; } virtual double area() const = 0; // 纯虚函数(抽象类) }; // 派生类重写虚函数C++11 起可用 override 明确标注) class Circle : public Shape { public: void draw() override { // 显式标注 override(避免拼写错误) std::cout << "Drawing circle" << std::endl; } double area() const override { return 3.14 * radius * radius; } private: double radius = 5.0; }; int main() { Shape* shape = new Circle(); // 基类指针指向派生类对象 shape->draw(); // 输出 "Drawing circle"(动态绑定) std::cout << "Area: " << shape->area() << std::endl; delete shape; // 手动释放内存 return 0; } ``` --- #### 三、**关键注意事项** 1. **虚析构函数** C++ 中若基类指针指向派生类对象,**基类析构函数必须声明为 `virtual`**,否则可能只释放基类部分内存: ```cpp class Base { public: virtual ~Base() {} // 虚析构函数 }; ``` 2. **多重继承问题** C++ 允许多重继承,但需用 `virtual` 继承解决菱形继承问题: ```cpp class A {}; class B : virtual public A {}; // 虚继承 class C : virtual public A {}; class D : public B, public C {}; // 避免 A 的成员重复 ``` 3. **访问权限控制** C++ 支持更细粒度的继承权限(如 `protected` 继承限制基类成员对外暴露)。 --- #### 四、**对比总结** - **语法差异**:C++ 需要显式标注 `virtual` 和 `override`,Java 默认方法可重写。 - **内存管理**:C++ 需手动释放对象(`delete`),Java 依赖垃圾回收。 - **设计哲学**:C++ 强调灵活性(如多重继承),Java 强调简洁性(单继承 + 接口)。 --- **学习建议**:通过调试观察 C++ 虚函数表的内存布局,理解动态绑定的底层机制,同时注意避免 Java 习惯导致的 C++ 内存泄漏问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值