C++面试题-面向对象-面向对象概念

C++面试题-面向对象-面向对象概念

问:说说C++C的主要区别?

答:

  1. C语言属于面向过程语言,通过函数来实现程序功能。而C++是面向对象语言,主要通过类的形式来实现程序功能。
  2. 使用C++编写的面向对象应用程序比C语言编写的程序更容易维护、扩展性更强。
  3. C++多用于开发上层应用软件,而C语言代码体积小、执行效率高,多编写系统软件和嵌入式开发。

例如:Windows操作系统、Linux操作系统大部分内核都是用C语言编写的。从名称上,可以说C++C语言的超集,它兼容C语言,同时扩充了许多内容,例如面向对象、STL模板库等。总之,C语言属于面向过程编程语言,侧重于函数;而C++属于面向对象编程语言,侧重于类。

 

问:面向对象的程序设计思想是什么?

答:把数据结构和对数据结构进行操作的方法封装形成一个个的对象。

 

问:面向对象与面向过程分别是什么?

答:

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;以过程为中心的编程思想,以算法进行驱动。

面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。以对象为中心,以消息进行驱动。

 

问:面向过程与面向对象的优缺点?

答:

面向过程

  1. 优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源,比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
  2. 缺点:没有面向对象易维护、易复用、易扩展。

面向对象

  1. 优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护。
  2. 缺点:性能比面向过程低。

 

问:面向对对象与面向过程的区别?

答:

  1. 面向过程的思维方式是分析综合。面向对象的思维方式是构造。
  2. 面向过程的程序设计有挑战性,技巧性强。面向对象主要在于对象抽象有技术性,抽象完了后,任何人都可以做后面的工作了。
  3. 对面向过程而言,数据是独立的。在面向对象中,对象本身就提供了存储数据的空间(类的数据成员),这样就是函数的参数传递简单多了,而且提供了数据封装后,数据的访问也变可靠了。

 

问:什么是对象?

答:对象是指现实世界中各种各样的实体。它可以指具体的事物也可以指抽象的事物。

 

问:对象都具有二方面特征是什么?分别是什么含义?

答:对象都具有的特征是:静态特征和动态特征。

静态特征是指能描述对象的一些属性,动态特征是指对象表现出来的行为。

 

问:什么是类?

答:类是一种复杂的数据类型,它是将不同类型的数据和与这些数据相关的操作封装在一起的集合体。类的基本思想是数据抽象和封装。数据抽象是一种依赖于接口和实现分离的编程(以及设计)技术。类的接口包括用户所能执行的操作:类的实现则包括类的数据成员、负责接口实现的函数以及定义类所需的各种私有函数。

封装实现了类的接口和实现的分离。封装后的类隐藏了它的实现细节,也就是说,类的用户只能使用接口而无法访问实现部分。类想要实现数据抽象和封装,需要首先定义一个抽象数据类型。在抽象数据类型中,由类的设计者负责考虑类的实现过程;(摘自《Primer c++第五版》)

关于接口和实现分离的技术(某网友的博客文章):https://blog.csdn.net/starlee/article/details/610825

 

问:写出结构体定义与声明的几种形式?

答:struct为结构体关键字,tag为结构体的标志,member-list为结构体成员列表,其必须列出其所有成员;variable-list为此结构体声明的变量。

struct tag {

 member-list

} variable-list ;

在一般情况下,tagmember-listvariable-list3部分至少要出现2个。以下为示例:

1. // 此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c。同时又声明了结构体变量s1,这个结构体并没有标明其标签。

struct {

    int a;

    char b;

    double c;

} s1;

2. // 同上声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c,结构体的标签被命名为SIMPLE,没有声明变量。

struct SIMPLE{

    int a;

    char b;

    double c;

};

// SIMPLE标签的结构体,另外声明了变量t1t2t3

struct SIMPLE t1, t2[20], *t3;

3.// 也可以用typedef创建新类型

typedef struct{

    int a;

    char b;

    double c;

} Simple2;

//现在可以用Simple2作为类型声明新的结构体变量

Simple2 u1, u2[20], *u3;

4.// 此结构体的声明包含了其他的结构体

struct COMPLEX{

    char string[100];

    struct SIMPLE a;

};

// 此结构体的声明包含了指向自己类型的指针

struct NODE{

    char string[100];

    struct NODE *next_node;

};

5. struct B;   

// 对结构体B进行不完整声明

// 结构体A中包含指向结构体B的指针

struct A{

    struct B *partner;

    //other members;

};

// 结构体B中包含指向结构体A的指针,在A声明完后,B也随之进行声明

struct B{

    struct A *partner;

    //other members;};

 

问:类与结构体的区别是什么?

答:

  1. 只有结构体存在于C语言,结构体和类都存在于C++
  2. C中结构体只涉及到数据结构,在C++中结构体和类体现了数据结构和算法的结合。也就是说在C++中,结构体还可以包含函数,而C语言中不可以。
  3. C语言中结构体没有成员函数,可以被声明为变量、指针和数组等。在C++中由于对结构体进行了扩充,获取了很多功能,当然还可以包含函数。
  4. 访问机制,结构体默认访问的机制是public,而类默认访问机制是private
  5. class继承默认是private继承,而从struct继承默认是public继承。
  6. C++的结构体声明不必有struct关键字,而C语言的结构体声明必须带有关键字(使用typedef别名定义除外)。
  7. 结构体是值类型,而类是引用类型。
  8. 结构体和类同样可以能够继承和实现多态。
  9. C++中,结构体可以继承类,类同样也可以继承结构体,继承过程中注意访问权限。
  10. class”这个关键字还用于定义模板参数,就像“typename”。但关键字“struct”不用于定义模板参数。这一点在Stanley B.Lippman写的Inside the C++ Object Model有过说明。
  11. struct更适合看成是一个数据结构的实现体,class更适合看成是一个对象的实现体。
  12. 实例化的类存储在内存的堆内,而结构存储在栈内,结构的执行效率相对较高。
  13. 结构体没有析构函数。

 

问:哪种使用的情况下适合结构体还是类?

答:

  1. 在表示诸如点、矩形等主要用来存储数据的轻量级对象时,首选struct
  2. 在表示数据量大、逻辑复杂的大对象时,首选class
  3. 在表现抽象和多级别的对象层次时,class是最佳选择。

 

问:什么是抽象?

答:抽象的作用就是表示同一类事物的本质。例如在c/c++中,数据类型就是对一批具体的数的抽象。

类是对象的抽象,而对象则是类的特例,或者说是实例。

抽象包括两个方面:一是过程抽象,二是数据抽象。

 

问:什么是封装?

答:封装是指可以对一个对象进行封装处理,把它的一部分属性和功能对外界屏蔽,也就是说从外界是看不到的,甚至是不可见的。

封装的特点:

  1. 将有关的数据和操作代码封装在一个对象中,形成一个基本单位,各个对象之间相对独立,互不干扰。
  2. 将对象中某些部分对外隐蔽,只留下少数接口,以便与外界联系,接收外界的消息。这种对外界屏蔽的做法称为消息屏蔽。

 

问:继承的作用?

答:采用继承的方法可以很方便地利用一个已有的类建立一个新的类,这就可以重用已有软件中的一部分甚至大部分,节省了编程工作量。

 

问:类的特性?

答:封装(维护性),继承(复用性)和多态(扩展性)。抽象,不属于类的特性,特点是灵活性。

 

问:抽象类是什么?作用是什么?

答:抽象类是一种特殊的类,它是为了抽象和设计的目的为建立的,它处于继承层次结构的较上层。

  1. 抽象类的定义:称带有纯虚函数的类为抽象类。
  2. 抽象类的作用:抽象类的主要作用是将有关的操作作为结果接口组织在一个继承层次结构中,由它来为派生类提供一个公共的根,派生类将具体实现在其基类中作为接口的操作。所以派生类实际上刻画了一组子类的操作接口的通用语义,这些语义也传给子类,子类可以具体实现这些语义,也可以再将这些语义传给自己的子类。
  3. 使用抽象类时注意:抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类中没有重新定义纯虚函数,而只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体的类。抽象类是不能定义对象的。

 

问:什么是接口类?特点是什么?

答:接口类就是只提供接口不提供实现的类,就是接口类,接口类和抽象类对C++而言,没有什么区别。

接口类有如下特点:

  1. 子类来实现接口类中没有实现的所有接口。
  2. 接口方法前面有virtual关键词修饰,并且等于0
  3. 只能被继承,不能独自生成对象。

 

问:什么是友元类?

答:类可以允许其他类或者函数访问它的非公有成员,方法是令其他类或者函数成为它的友元(friend)。如果类想把一个函数作为它的友元,只需要增加一条以friend关键字开始的函数声明语句即可。

 

问:多重继承与多继承的区别?

答:多继承是指一个子类继承多个父类。多继承对父类的个数没有限制,继承方式可以是公共继承、保护继承和私有继承。

多重继承特点总结如下:

  1. 多重继承与多继承不同,当B类从A类派生,C类从B类派生,此时称为多重继承
  2. 当实例化子类时,会首先依次调用所有基类的构造函数,最后调用该子类的构造函数;销毁该子类时,则相反,先调用该子类的析构函数,再依次调用所有基类的析构函数。
  3. 无论继承的层级有多少层,只要它们保持着直接或间接的继承关系,那么子类都可以与其直接父类或间接父类构成 is a的关系,并且能够通过父类的指针对直接子类或间接子类进行相应的操作,子类对象可以给直接父类或间接父类的对象或引用赋值或初始化。

 

问:在头文件中进行类的声明,在对应的实现文件中进行类的定义有什么意义?

答:这样可以提高编译效率。因为这样不仅文件的代码设计方便,而且只需要编译一次就能够生成.obj文件。再次应用该类的地方,就不会重新编译了。

 

问:如何定义两个类互为成员的情况?以下代码正确吗?

class A

{

public:

private:

 B m_B;

};

class B

{

private:

A m_A;

};

答:不正确。因为在类A之前,没有发现类B的定义,直接使用了类B,但是却没有发现类B的定义,而只是发现了类B的声明。修改代码为:

classB

class A

{

public:

private:

 B *m_B;//或者B m_B();

};

class B

{

private:

A m_A;

};

分析:

本题笔者认为主要考点是类的定义与声明的区别。

B m_B只是类B的声明,而 B *m_B;//或者B m_B();是类B的定义。

当我们new出一个对象(B *m_B),就会自动调用构造函数完成初始化,也就完成了类的定义。

当我们B m_B()时,由于m_B()意思是调用了类B默认的构造函数,完成类的定义。

类的定义与类的声明区别就在于定义时是自动调用了构造函数,因此才真正创建一个对象m_B,而声明并没有调用构造函数,所以也没有创建对象,只是声明而已。

 

问:成员变量有哪些访问方式(或者访问控制方式)?

答:成员变量根据访问权限有privateprotectpublic 3种访问方式。

 

问:C++中的private的成员变量可以由哪些函数访问?

答:private只能由本类中的成员函数或者友元函数来访问。

  • 3
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面向对象程序设计》试题 一、单选题(每空2分,共40分) 1、关于C++与C语言关系的描述中,( )是错误的。 A.C语言是C++语言的一个子集 B.C语言与C++语言是兼容的 C.C++语言对C语言进行了一些改进 D.C++语言和C语言都是面向对象的 2、已知:int m=10; 下列表示引用的方法中,( )是正确的。 A.int& x=m; B.int& y=10; C.int& z; D.float& t=&m; 3、考虑下面的函数原型声明: void DefPar(int a, int b=7, char z = '*'); 下面函数调用中,不合法的是( )。 A.DefPar(5); B.DefPar(5,8); C.DefPar(5,'#'); D.DefPar(0,0,'*'); 4、系统在调用重载函数时往往根据一些条件确定哪个重载函数被调用,在下列选项中,不能作为依据的是( )。 A.函数的返回值类型 B.参数的类型 C.函数名称 D.参数个数 5、下列有关C++类的说法中,不正确的是( )。 A.类是一种用户自定义的数据类型 B.只有类中的成员函数或类的友元函数才能存取类中的私有成员 C.在类中,如果不做特别说明,所有成员的访问权限均为私有的 D.在类中,如果不做特别说明,所有成员的访问权限均为公用的 6、已知X类,则当程序执行到语句X array[3];时,调用了( )次构造函数。 A.0 B.1 C.2 D.3 7、有关析构函数的说法,不正确的是( )。 A.析构函数有且仅有一个 B.析构函数和构造函数一样可以有形参 C.析构函数的功能是在系统释放对象之前作一些内存清理工作 D.析构函数无任何函数类型 8、类定义的内容允许被其对象无限制地存取的是( )。 A.private 部分 B. protected 部分 C.public 部分 D.以上都不对 9、关于常数据成员的说法,不正确的是( )。 A.常数据成员的定义形式与一般常变量的,只不过常数据成员的定义必须出现在类体中 B.常数据成员必须进行初始化,并且不能被更新 C.常数据成员通过构造函数的成员初始化列表进行初始化 D.常数据成员可以在定义时直接初始化 10、运用运算符delete删除一个动态对象时( )。 A.系统首先为该动态对象调用构造函数,再释放其占用的内存 B.系统首先释放该动态对象占用的内存,再为其调用构造函数 C.系统首先为该动态对象调用析构函数,再释放其占用的内存 D.系统首先释放动态对象占用的内存,再为其调用析构函数 11、可在类外用p.a的形式访问派生类对象 p的基类成员a,其中a是( )。 A.私有继承的公用成员 B.公用继承的私有成员 C.公用继承的保护成员 D.公用继承的公用成员 12、在公用继承方式下,有关派生类对象和基类对象的关系,不正确的叙述是(  )。 A.派生类的对象可以赋给基类的对象 B.派生类的对象可以初始化基类的引用 C.派生类的对象可以直接访问基类中的成员 D.派生类的对象的地址可以赋给指向基类的指针 13、设置虚基类的目的是( )。 A.简化程序 B.消除二义性 C.提高运行效率 D.减少目标代码 14、在C++中,用于实现动态多态性的是( )。 A.内联函数 B.重载函数 C.模板函数 D.虚函数 15、不能说明为虚函数的是( )。 A.析构函数 B.构造函数 C.类的成员函数 D.以上都不对 16、如果一个类至少有一个纯虚函数,那么就称该类为( )。 A.抽象类 B.派生类 C.纯基类 D.以上都不对 17、下面关于友元的描述中,错误的是( )。 A.友元函数可以访问该类的私有数据成员 B.一个类的友元类中的成员函数都是这个类的友元函数 C.友元可以提高程序的运行效率 D.类与类之间的友元关系可以继承 18、下列运算符中,( )运算符在C++中不能被重载。 A.&& B.[ ] C.:: D.new 19、模板的使用实际上是将类模板实例化成一个( )。 A.函数 B.对象 C.类 D.抽象类 20、假定MyClass为一个类,则该类的拷贝构造函数的声明语句为( )。 A.MyClass(MyClass x) B.MyClass&(MyClass x) C.MyClass(MyClass &x) D.MyClass(MyClass *x) 二、填空题(前16个空,每空1分,后2个空,每空2分,共20分) 1、类和对象的关系可表述为:类是对象的 ,而对象则是类的 。 2、在C++中,三种继承方式的说明符号为 、 和 ,如果不加说明,则默认的继承方式为 。 3、如果只想保留公共基类的一个复制,就必须使用关键字 把这个公共基类声明为虚基类。 4、若要把void fun( )定义为类A的友元函数,则应在类A的定义中加入语句 。 5、类的静态成员分为 和 。 6、运算符重载要求保持其原来的操作数个数、 、 和语法结构。 7、通过关键字 可以声明模板,通过关键字 指定函数模板的类型参数,有几个类型参数就有几个类型关键字。 8、列出C++中两种用户自定义的数据类型: 、 。 9、构造函数的作用是 。 10、后置自增运算符“++”重载为类的成员函数(设类名为A)的形式为 。 三、阅读下面3个程序,写出程序运行时输出的结果:(共13分) 1、#include <iostream> using namespace std; void fun(int &a,int &b) { int p; p=a; a=b; b=p; } void exchange(int &a,int &b,int &c) { if(a<b) fun(a,b); if(a<c) fun(a,c); if(b<c) fun(b,c); } void main() { int a=12,b=89,c=56; exchange(a,b,c); cout<<"a="<<a<<",b="<<b<< ",c="<<c<<endl; } 2、#include <iostream> using namespace std; class Date { public: Date(int,int,int); Date(int,int); Date(int); Date(); void display(); private: int month, day, year; }; Date::Date(int m, int d, int y) : month(m),day(d),year(y) { } Date::Date(int m,int d):month(m),day(d) { year=2009; } Date::Date(int m) : month(m) { day=1; year=2010; } Date::Date() { month=1; day=1; year=2010; } void Date::display() { cout <<month<<"/"<<day<<"/"<<year<<endl; } void main() { Date d1(12,31,2009); Date d2(12,31); Date d3(1); Date d4; d1.display(); d2.display(); d3.display(); d4.display(); } 3、#include <iostream> using namespace std; class A { public: A() { cout<<"constructing A "<<endl; } ~A() { cout<<"destructing A "<<endl; } }; class B: public A { public: B() { cout<<"constructing B "<<endl; } ~B() { cout<<"destructing B "<<endl; } }; class C : public B { public: C() { cout<<"constructing C "<<endl; } ~C() { cout<<"destructing C "<<endl; } }; void main() { C c1; } 四、编程题(共27分) 1、(10分)已知复数类Complex的声明如下: class Complex { public: Complex(); Complex(double); Complex(double, double); friend Complex operator + (Complex&, Complex&); friend ostream & operator << (ostream&, Complex&); friend istream& operator >> (istream&, Complex&); private: double real, imag; }; 要求: (1)写出该类的所有构造函数的类外定义代码。 (2)写出对运算符“+”、“<<”、“>>”进行重载的运算符重载函数的定义。 2、(17分)下列Base类是一个表示形状的抽象类,area( )为求图形面积的函数,total( )则是一个通用的用以求不同形状的图形面积总和的函数。 class Base { public: virtual double area()=0; }; double total(Base *s[ ], int n) { double sum=0.0; for(int i=0; i<n; i++) sum+=s[i]->area( ); return sum; } 要求: (1)从Base类派生圆类(Circle)、正方形类(Square),圆类新增数据成员半径(radius),正方形类新增数据成员边长(a),圆类和正方形类都有构造函数,修改、显示数据成员值的函数,求面积函数。 (2)写出main( )函数,计算半径为5.5的圆和边长为9.9的正方形的面积和(必须通过调用total函数计算)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值