1,构造函数中调用虚函数的问题。
注:一般编译器都会在执行完base subject的构造函数和调用用户代码之前,实施当前对象vptr的初始化工作。
因此,如果当前对象内定义了某函数,构造函数中调用的一定是当前对象内的,virtual可以认为不存在。
实例代码:
#include <iostream>
using namespace std;
class Base
{
public:
Base()
{
f();
}
virtual void f()
{
cout << "Base" << endl;
}
};
class Derive : public Base
{
public:
Derive()
{
f();
}
virtual void f()
{
cout << "Derive" << endl;
}
};
int main()
{
Derive d;
return 0;
}
输出:
Base
Derive
这种布局不好,构造函数中调用virtual函数,可以等价认为virtual根本不存在.
2,
#include <iostream>
using namespace std;
class Base
{
public:
virtual void f()
{
cout << "Base" << endl;
}
};
class Derive : public Base
{
public:
virtual void f()
{
cout << "Derive" << endl;
}
};
int main()
{
Derive* d = new Derive;
d -> f();
Base* b = d;
b -> f(); //正常的多态性
Base* b2 = (Base*)d;
b2 -> f(); //输出Derive
//原因:这里只是指针赋值,b2所指对象的vptr没有改变,所以调用Derive函数。
Base b3 = (Base)(*d);
b3.f(); //输出Base
//原因:d的基类部分,b3执行copy constructor, b3.f(),静态绑定.
}
3,
#include <iostream>
#include <cstdio>
using namespace std;
class A
{
public:
A()
{
func(0); //非常不好的布局,构造函数调用虚函数,可认为virtual不存在.
};
virtual void func(int data)
{
printf("A1 :%d\n",data);
}
virtual void func(int data) const
{
printf("A2 :%d\n",data);
}
void func(char *str)
{
printf("A3 %s)\n",str);
}
};
class B : public A
{
public:
void func()
{
printf("B1 :%s\n","");
}
void func(int data)
{
printf("B2 :%d\n",data);
}
void func(char *str)
{
printf("B3 %s)\n",str);
}
};
int main()
{
A *pA;
B b;
//输出 A1 :0 调用了A的构造函数
pA=&b;
pA->func(1);
//子类指针赋值给基类指针,调用virtual函数, 多态性执行子类 输出 B2 :1
pA->func("test");
//func(char *str) 非virtual函数,静态绑定,执行基类 输出 A3 test)
A().func(1);
//基类先执行构造函数 输出 A1 :0 后调用成员函数 输出 A1 :1
const A *pcA;
pcA=&b;
pcA->func(2);
//多态性,但是子类没有重载virtual void func(int data) const,默认采用基类的实现, 输出 A2 :2
return 0;
}
分享到:
相关推荐
C++是一种强大的编程语言,以其丰富的特性,尤其是面向对象编程(OOP)而闻名。...通过学习这些知识点,开发者可以更好地掌握C++的面向对象编程,提高编程效率,同时也能为解决复杂问题提供强大的工具。
《.Net 面向对象及设计模式总结》是一份深度涵盖.Net开发中面向对象编程原理和设计模式的宝贵资料,特别适合初学者巩固基础知识,以及有经验的开发者进行复习和提升。通过阅读这些笔记,我们可以深入理解面向对象的...
算法分解(algorithmic decomposition)和面向对象分解是两种常见的方法。算法分解采用自顶向下结构化设计,而面向对象分解通过重用公共机制生成更小的系统,提高了效率和表达力。 面向对象分解具有显著优势,如...
7. 设计模式:设计模式是解决问题的通用模板,它们总结了面向对象设计中常见问题的解决方案。常见的设计模式包括工厂模式、单例模式、装饰模式、观察者模式等。 8. 系统分析:系统分析阶段是理解问题和需求的过程,...
面向对象分析(Object-Oriented Analysis,OOA)是软件工程中的一种重要方法,它着重于从实际问题出发,抽象出问题域内的对象及其相互关系,以构建问题域模型。在“软件工程-张海藩编著--面向对象分析实验报告”中,...
本书内容由浅入深,紧密结合实际,利用大量典型实例,详细讲解Java面向对象的编程思想、编程语法和设计模式,介绍常见Java类库的用法,总结优化 Java编程的各种宝贵经验,深入阐述Java虚拟机执行Java程序的原理。...
### Java面向对象知识点总结 #### 1. 类与对象 **1.1 类** - **概念**: 类是用来描述一类事物的共性内容的抽象模型。 - **创建**: 创建类时,需要考虑该类所描述的对象应该具备哪些属性(特征)和行为(功能)。 ...
在C#编程中,面向对象的设计模式是一种组织代码和解决常见问题的有效方法。设计模式是对在软件设计中经常出现的某类问题的通用解决方案的描述,它是在特定上下文中最佳实践的结果。本篇文章将对一系列重要的C#面向...
在这个资源中,我们将总结一些Java基础常见问题,涵盖面向对象、构造方法、接口、抽象类、String和Object等方面的知识点。 1. 面向对象编程 面向对象编程是一种编程范式,它将问题解决方式从面向过程转换为面向...
10. **设计模式**:面向对象设计模式是解决常见问题的模板,如单例模式、工厂模式、观察者模式等,它们是经验的总结,可以帮助开发者编写出高质量的代码。 马石安老师的教案会详细讲解这些概念,并通过实例和练习...
在JavaScript编程领域,面向对象是一种常见的编程范式,它允许我们以类和对象的方式来组织代码,使得代码结构更清晰、可维护性更强。本案例"js 贪吃蛇(面向对象)"就是一个很好的示例,它将经典的贪吃蛇游戏实现为...
设计模式是在特定上下文中解决问题的模板,是面向对象设计的实践经验总结。常见的设计模式有工厂模式、单例模式、观察者模式、装饰器模式等,它们提供了在特定场景下设计类和对象的通用解决方案。 面向对象编程不仅...
在软件开发领域,编程范式是组织代码的方式,常见的编程范式包括面向过程编程(Procedural Programming)和面向对象编程(Object-Oriented Programming,简称OOP)。这两种编程范式在解决问题时有着不同的思维方式和...
总结来说,"面向对象分析与设计"主题涵盖了大量的理论知识和实践经验,包括面向对象的基本概念、设计原则、设计模式以及在Java项目中的实际应用。通过学习相关书籍和研究实际项目源码,开发者可以提升自己的面向对象...
在Java面向对象课程设计中,常见的知识点包括: 1. 类和对象:如何定义类,包括属性和方法的声明,以及构造函数的使用。 2. 封装:理解访问修饰符(public, private, protected, default),以及如何通过getter和...
5. **第五章设计模式简介**:设计模式是解决常见软件设计问题的经验总结,本章会概述一些常见的设计模式,如工厂模式、单例模式等。 6. **第六章细化迭代1:分析**:在迭代开发过程中,分析阶段至关重要,本章将...
8. **设计模式**:设计模式是解决软件设计中常见问题的经验总结,如单例模式、工厂模式、观察者模式等。这些模式提供了解决特定问题的标准方法,提高代码的可读性和可维护性。 9. **接口与实现**:接口是一组方法的...
面向对象程序设计语言C++重点难点复习题及答案总结 面向对象程序设计语言C++是一种功能强大且广泛应用的程序设计语言,作为一名程序员,掌握C++语言的重点难点是非常重要的。本文将对C++面向对象程序设计语言的重点...
面向对象设计模式是软件开发中的一种重要思想,它通过总结和提炼在软件设计过程中常见的问题和解决方案,形成了可复用的设计规范。标题提到的“23种面向对象设计模式”涵盖了设计模式的主要分类,这些模式在Java、...