构造函数的继承 C#
- 格式:docx
- 大小:18.20 KB
- 文档页数:4
一.单项选择题(每题2分,共30分)1.若数组a定义为int[][]a=new int[3][4],则a是(B )。
A.一维数组B.二维数组C.三维数组D.四维数组2.下列关于for循环和while循环的说法中(A )是正确的。
A、while循环能实现的操作,for循环也都能实现B、while循环判断条件一般是程序结果,for循环判断条件一般是非程序结果C、两种循环任何时候都可替换D、两种循环结构中循环体都不可以为空3.void 的含义为(C )。
A.方法体为空B.定义的方法没有形参C.定义的方法没有返回值D.方法的返回值不能参加算术运算4.以下有关类的构造函数继承的说明,正确的是(C )。
A.子类继承父类的构造函数,但不能自己定义B.子类可定义自己的构造函数,但受父类定义的构造函数的限制C.子类和父类均可独自定义自己的构造函数,但执行时的顺序有规定D.如父类定义了构造函数,则子类只能继承父类的构造函数,不能自己定义5.下面说法正确的是(C )。
A.Java语言里的线程不是对象B.Java中任何可执行的类都需要main方法C.Java语言的类都是ng.Object的子类D.double是Java语言合法的标识符6.下列属于容器的组件有(B )。
A.Button B.Panel C.线程D.TextArea7.在Java语言中,不允许使用指针体现出的Java特性是( D )。
A.可移植B.解释执行C.健壮性D.安全性8.下列方法中,不属于WindowListener接口的是(D )。
A.windowOpened() B.windowClosed()C.windowActivated() D.mouseDragged()9.下列关于Applet的说法中,错误的是(C )。
A.Applet自身不能运行,必须嵌入到其它应用程序(如浏览器)中运行;B.可以在安全策略的控制下读写本地磁盘文件;C.Java中不支持向Applet传递参数;D.Applet的主类要定义为java.applet.Applet类的子类10.在Applet中显示文字、图形等信息时,应使用的方法是( A )。
前面我们说基类的成员函数可以被继承,可以通过派生类的对象访问,但这仅仅指的是普通的成员函数,类的构造函数不能被继承。
构造函数不能被继承是有道理的,因为即使继承了,它的名字和派生类的名字也不一样,不能成为派生类的构造函数,当然更不能成为普通的成员函数。
在设计派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数完成,但是大部分基类都有private 属性的成员变量,它们在派生类中无法访问,更不能使用派生类的构造函数来初始化。
这种矛盾在C++继承中是普遍存在的,解决这个问题的思路是:在派生类的构造函数中调用基类的构造函数。
下面的例子展示了如何在派生类的构造函数中调用基类的构造函数:1.#include<iostream>ing namespace std;3.4.//基类People5.class People{6.protected:7.char*m_name;8.int m_age;9.public:10.People(char*,int);11.};12.People::People(char*name,int age):m_name(name),m_age(age){}13.14.//派生类Student15.class Student:public People{16.private:17.float m_score;18.public:19.Student(char*name,int age,float score);20.void display();21.};22.//People(name, age)就是调用基类的构造函数23.Student::Student(char*name,int age,float score):People(name, age),m_score(score){}24.void Student::display(){25.cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<"。
C++——类继承以及类初始化顺序对于类以及类继承, ⼏个主要的问题:1) 继承⽅式: public/protected/private继承.这是c++搞的, 实际上继承⽅式是⼀种允许⼦类控制的思想. ⼦类通过public继承, 可以把基类真实还原, ⽽private继承则完全把基类屏蔽掉.这种屏蔽是相对于对象层⽽⾔的, 就是说⼦类的对象完全看不到基类的⽅法, 如果继承⽅式是private的话, 即使⽅法在基类中为public的⽅法.但继承⽅式并不影响垂直⽅向的访问特性, 那就是⼦类的函数对基类的成员访问是不受继承⽅式的影响的.⽐较(java): java是简化的, 其实可认为是c++中的public继承. 实在没必要搞private/protected继承, 因为如果想控制,就直接在基类控制就好了.2) 对象初始化顺序: c++搞了个成员初始化列表, 并确明确区分初时化跟赋值的区别. c++对象的初始化顺序是:(a) 基类初始化(b) 对象成员初时化(c) 构造函数的赋值语句举例:假设 class C : public A, public B {D d;//}则初始化的顺序是A, B, D, C的构造函数.这⾥基类的初始化顺序是按照声明的顺序, 成员对象也是按照声明的顺序. 因此 c(int i, int j) : B(i), A(j) {} //这⾥成员初始化列表的顺序是不起作⽤的;析构函数的顺序则刚好是调过来, 构造/析构顺序可看作是⼀种栈的顺序;⽐较(java): java中初始化赋值是⼀回事. ⽽且对基类的构造函数调⽤必须显⽰声明, 按照你⾃⼰写的顺序.对成员对象, 也叫由你初始化.没有什么系统安排的顺序问题, 让你感觉很舒服;3) 多继承问题: c++⽀持多继承, 会导致"根"不唯⼀. ⽽java则没有该问题;此外c++没有统⼀的root object, java所有对象都存在Object类使得很多东西很⽅便. ⽐如公共的seriall, persistent等等.4) 继承中的重载: c++中, 派⽣类会继承所有基类的成员函数, 但构造函数, 析构函数除外.这意味着如果B 继承A, A(int i)是基类构造函数, 则⽆法B b(i)定义对象. 除⾮B也定义同样的构造函数.c++的理由是, 假如派⽣类定义了新成员, 则基类初始化函数⽆法初始化派⽣类的所有新增成员.⽐较(java): java中则不管, 就算有新增对象基类函数没有考虑到, ⼤不了就是null, 或者你⾃⼰有缺省值. 也是合理的.5) 继承中的同名覆盖和⼆义性: 同名覆盖的意思是说, 当派⽣类跟基类有完全⼀样的成员变量或者函数的时候, 派⽣类的会覆盖基类的.类似于同名的局部变量覆盖全局变量⼀样. 但被覆盖的基类成员还是可以访问的.如B继承A, A, B都有成员变量a,则B b, b.a为访问B的a, b.A::a 则为访问基类中的a. 这对于成员函数也成⽴.但需要注意的是, 同名函数必须要完全⼀样才能覆盖. int func(int j)跟int func(long j)其实是不⼀样的. 如果基类,派⽣类有这两个函数, 则不会同名覆盖.最重要的是, 两者也不构成重载函数. 因此假如A有函数int func(int j), B有函数int func(long j). 则B的对象b.func(int)调⽤为错误的. 因为B中的func跟它根本就不构成重载.同名覆盖导致的问题是⼆义性. 假如C->B=>A, 这⾥c继承B, B继承A. 假如A, B都有同样的成员fun, 则C的对象c.fun存在⼆义性. 它到底是指A 的还是B的fun呢?解决办法是⽤域限定符号c.A::fun来引⽤A的fun.另外⼀个导致⼆义性的是多重继承. 假设B1, B2都继承⾃B, D则继承B1, B2. 那么D有两个B⽽产⽣⼆义性.这种情况的解决办法是⽤虚基类. class B1 : virtual public B, class B2:virtual public B, D则为class D : public B1, public B2. 这样D中的成员只包含⼀份B的成员使得不会产⽣⼆义性.⽐较(java). java中是直接覆盖. 不给机会这么复杂, 还要保存基类同名的东西. 同名的就直接覆盖, 没有同名的就直接继承.虚基类的加⼊, 也影响到类的初始化顺序. 原则是每个派⽣类的成员化初始化列表都必须包含对虚基类的初始化.最终初始化的时候, 只有真正实例化对象的类的调⽤会起作⽤. 其它类的对虚基类的调⽤都是被忽略的. 这可以保证虚基类只会被初始化⼀次.c++没有显式接⼝的概念, 我觉得是c++语⾔的败点. 这也是导致c++要⽀持组件级的重⽤⾮常⿇烦. 虽然没有显式的接⼝, 但c++中的纯虚函数以及抽象类的⽀持, 事实上是等同于接⼝设施的. 当⼀个类中, 所有成员函数都是纯虚函数, 则该类其实就是接⼝.java c++接⼝类(所有成员函数都是纯虚函数)抽象类类(部分函数是虚函数)对象类对象类C++构造函数调⽤顺序1. 如果类⾥⾯有成员类,成员类的构造函数优先被调⽤;2. 创建派⽣类的对象,基类的构造函数优先被调⽤(也优先于派⽣类⾥的成员类);3. 基类构造函数如果有多个基类,则构造函数的调⽤顺序是某类在类派⽣表中出现的顺序⽽不是它们在成员初始化表中的顺序;4. 成员类对象构造函数如果有多个成员类对象,则构造函数的调⽤顺序是对象在类中被声明的顺序⽽不是它们出现在成员初始化表中的顺序;5. 派⽣类构造函数,作为⼀般规则派⽣类构造函数应该不能直接向⼀个基类数据成员赋值⽽是把值传递给适当的基类构造函数,否则两个类的实现变成紧耦合的(tightly coupled)将更加难于正确地修改或扩展基类的实现。
C++在单继承、多继承、虚继承时,构造函数、复制构造函数、赋值操作符、析构函数的执⾏顺序和执⾏内容⼀、本⽂⽬的与说明1. 本⽂⽬的:理清在各种继承时,构造函数、复制构造函数、赋值操作符、析构函数的执⾏顺序和执⾏内容。
2. 说明:虽然复制构造函数属于构造函数的⼀种,有共同的地⽅,但是也具有⼀定的特殊性,所以在总结它的性质时将它单独列出来了。
3. 单继承、多继承、虚继承,既然都属于继承,那么虽然有⼀定的区别,但还是相同点⽐较多。
如果放在⼀块讲,但为了将内容制作成递进的,就分开了,对相同点进⾏重复,(⼤量的复制粘贴哈),但在不同点进⾏了标注。
注意:三块内容是逐步递进的如果你懂虚函数,那么单继承和多继承那块你就可以不看;如果你懂多继承,那单继承你就不要看了,⾄于虚继承就等你懂虚继承再回来看吧;如果你只懂单继承,那你就只看单继承就好。
⼆、基本知识1. 对于⼀个空类,例如:class EmptyClass{};虽然你没有声明任何函数,但是编译器会⾃动为你提供上⾯这四个⽅法。
class EmptyClass {public:EmptyClass(); // 默认构造函数EmptyClass(const EmptyClass &rhs); // 复制构造函数~EmptyClass(); // 析构函数EmptyClass& operator=(const EmptyClass &rhs); // 赋值运算符}对于这四个⽅法的任何⼀个,你的类如果没有声明,那么编译器就会⾃动为你对应的提供⼀个默认的(注意合成默认构造函数是⽤于没有编写构造函数编译器才会合成默认构造函数,其中复制构造函数也是构造函数)。
(在《C++ primer》中,这个编译器⾃动提供的版本叫做“合成的***”,例如合成的复制构造函数)当然如果你显式声明了,编译器就不会再提供相应的⽅法。
2. 合成的默认构造函数执⾏内容:如果有⽗类,就先调⽤⽗类的默认构造函数。
继承类的构造函数
一、继承类的构造函数
1、概念
继承类的构造函数是指继承类继承了基类的数据成员和成员函数,但又要完成一定的初始化工作,满足自己的要求时,它就需要有自己的构造函数来完成这件事情。
2、使用方法
在构造函数中,首先要通过使用基类的构造函数,来完成基类的数据成员的初始化,这样可以确保基类数据成员的正确性。
然后再使用继承类的构造函数来完成自己的初始化工作。
例如,有一个类 Line,它继承了 Point 类:
class Line:public Point
{
public:
Line(int x1,int y1,int x2,int y2):Point(x1,y1)
{
m_x2 = x2;
m_y2 = y2;
}
private:
int m_x2;
int m_y2;
};
在上面的构造函数中,首先要使用基类 Point 的构造函数
Point(x1, y1) 来完成基类 Point 的数据成员的初始化,然后在继承类 Line 的构造函数中,再完成继承类 Line 自己的数据 m_x2 和m_y2 的初始化。
3、注意事项
(1)在 C++ 中,如果在子类的构造函数中没有显式的使用基类的构造函数,编译器会自动添加一个默认的基类构造函数,将基类成员变量设置为默认值。
(2)当子类构造函数中显式调用基类的构造函数时,则子类的成员变量将被赋予与基类构造函数相同的值。
(3)建议在子类的构造函数中显式地调用基类的构造函数,这能确保基类构造函数将被正确的调用,而不会出现意外的情况出现。
C++习题3(继承和多态)C++习题3(继承和多态)一、选择题1、在C++中,类与类之间的继承关系具有( C )A)自反性 B)对称性 C)传递性 D)反对称性2、在公有继承的情况下,基类的成员(私有的除外)在派生类中的访问权限( B )A)受限制 B)保持不变 C)受保护 D)不受保护3、按解释中的要求在下列程序划线处填入的正确语句是:( C )#include class Base{public:void fun(){cout<<"Base::fun"<<=""> fun()cout<<"Derived::fun"<fun();4、在保护继承的情况下,基类的成员(私有的除外)在派生类中的访问权限( C )A)受限制 B)保持不变 C)受保护 D)不受保护5、在哪种派生方式中,派生类可以访问基类中的protected 成员(B )A)public和private B)public、protected和private C)protected和private D)仅protected6、当一个派生类仅有protected继承一个基类时,基类中的所有公有成员成为派生类的(C)A)public成员 B)private成员 C)protected成员 D)友元7、不论派生类以何种方法继承基类,都不能使用基类的(B )A)public成员 B)private成员 C)protected成员 D)public成员和protected成员8下面叙述错误的是(S )。
A )基类的protected成员在派生类中仍然是protected的 B)基类的protected成员在public派生类中仍然是protected的C)基类的protected成员在private派生类中是private的 D)基类的protected 成员不能被派生类的对象访问9、下列说法中错误的是(S )。
子类继承父类构造函数
在C++中,子类继承了父类的构造函数。
当创建一个子类的对象时,父类的构造函数会被自动调用。
如果父类有多个构造函数,那么子类会继承所有这些构造函数。
在子类的构造函数中,可以通过使用super()函数来调用父类的构造函数。
这个函数必须在子类构造函数的第一行调用。
下面是一个例子:
class Parent {
public:
Parent(int a) {
// 父类的构造函数
}
};
class Child : public Parent {
public:
Child(int a, int b) : Parent(a) {
// 子类的构造函数,它调用了父类的构造函数
}
};
在这个例子中,Child类继承了Parent类,并且定义了一个自己的构造函数。
这个子类的构造函数在第一行调用了Parent类的构造函数。
这意味着当创建一个Child对象时,Parent类的构造函数也会被调用。
请注意,如果在子类的构造函数中没有显式地调用父类的构造函数,那么编译器会默认调用父类的无参数构造函数。
如果父类没有无参数的构造函数,那么必须显式地调用父类的某个构造函数。
1、在C++中,关于类的构造函数,下列说法错误的是:A. 构造函数的名字必须与类名完全相同B. 构造函数在对象创建时自动被调用C. 构造函数可以有返回类型D. 一个类可以有多个构造函数,通过重载实现(答案:C)2、下列关于C++中继承的说法,正确的是:A. 子类只能继承父类的一个构造函数B. 子类不能访问父类的私有成员C. 子类可以重写父类的所有成员函数,无论其访问权限如何D. C++支持多重继承,即一个子类可以同时继承多个父类(答案:D)3、在C++中,关于动态内存分配,下列说法正确的是:A. 使用new操作符分配的内存,不需要显式释放B. malloc和free是C++中推荐的动态内存分配和释放方式C. 使用delete操作符释放内存后,指针仍然指向原来的内存地址D. 动态分配的内存如果不使用delete或delete[]释放,可能会导致内存泄漏(答案:D)4、在C++中,下列哪个关键字用于声明一个虚函数?A. overrideB. finalC. virtualD. abstract(答案:C)5、关于C++中的模板,下列说法错误的是:A. 模板可以用于函数和类B. 模板实例化时,类型参数可以被具体类型替换C. 模板参数只能是类型参数,不能是值参数D. 使用模板可以提高代码的复用性和可维护性(答案:C)6、在C++中,关于异常处理,下列说法正确的是:A. try块中必须至少有一个catch块与之对应B. throw关键字用于抛出异常,其后可以跟任意类型的对象C. catch块只能捕获特定类型的异常D. 异常处理机制可以替代传统的错误返回码方式,使代码更清晰(答案:D)7、在C++中,关于STL(标准模板库)中的vector,下列说法错误的是:A. vector是一个动态数组,可以根据需要自动调整大小B. vector中的元素在内存中是连续存储的C. vector的push_back操作会在向量的开头插入一个新元素D. 使用vector之前需要包含头文件<vector>(答案:C)8、在C++中,关于多态性,下列说法正确的是:A. 多态性只能通过继承实现B. 多态性允许通过基类指针调用派生类的成员函数C. 多态性要求基类中的成员函数必须是虚函数D. 实现多态性时,基类的析构函数也应该是虚函数,以防止资源泄漏(答案:D)。
c类的继承和多态例子继承是面向对象编程中的重要概念之一,它允许一个类“继承”另一个类的属性和方法。
在C++中,继承分为三种类型:公有继承、私有继承和保护继承。
其中,公有继承是最常用的一种方式,也是实现多态的基础。
本文将通过一个例子来介绍C++中的公有继承和多态特性。
假设我们要设计一个动物园的系统,其中包含不同类型的动物。
首先,我们定义一个基类Animal,代表所有动物的共有属性和方法。
然后,派生出几个具体的动物类,如Lion(狮子)、Elephant (大象)和Monkey(猴子),它们都是Animal类的派生类。
1. 基类Animal的定义:```c++class Animal {public:Animal() {} // 构造函数virtual ~Animal() {} // 虚析构函数virtual void move() const = 0; // 纯虚函数,用于表示不同动物的移动方式protected:int age; // 年龄double weight; // 体重};```2. 派生类Lion的定义:```c++class Lion : public Animal {public:Lion(int a, double w) : Animal(), color("yellow") { age = a;weight = w;}void move() const {std::cout << "Lion is running." << std::endl;}private:std::string color; // 颜色};```3. 派生类Elephant的定义:```c++class Elephant : public Animal {public:Elephant(int a, double w) : Animal(), height(3.5) { age = a;weight = w;}void move() const {std::cout << "Elephant is walking." << std::endl; }private:double height; // 身高};```4. 派生类Monkey的定义:```c++class Monkey : public Animal {public:Monkey(int a, double w) : Animal(), num_bananas(5) {age = a;weight = w;}void move() const {std::cout << "Monkey is jumping." << std::endl;}private:int num_bananas; // 香蕉数目};```以上就是实现动物园系统的基本类定义。
全国计算机二级考试试题题库附完整答案(通用篇)一、选择题(每题2分,共20分)1.以下哪个不是Java的基本数据类型?A. intB. floatC. StringD. boolean答案:C2.在C++中,下面哪个选项是正确的关于构造函数的描述?A. 构造函数可以被继承B. 构造函数可以被重载C. 构造函数可以被继承和重载D. 构造函数不能被继承和重载答案:B3.以下哪个关键字用于定义常量?A. constB. staticC. volatileD. register答案:A4.在HTML中,以下哪个标签用于定义表格的标题?A. <table>B. <tabel>C. <title>D. <thead>答案:D5.以下哪个函数用于删除数组中的元素?A. array_push()B. array_pop()C. array_shift()D. array_unshift()答案:C6.以下哪个选项是JavaScript中的错误类型?A. SyntaxErrorB. ReferenceErrorC. TypeErrorD. All of the above答案:D7.以下哪个关键字用于定义接口?A. interfaceB. implementsC. extendsD. abstract答案:A8.以下哪个选项是Python中的列表推导式?A. [x x for x in range(5)]B. {x x for x in range(5)}C. (x x for x in range(5))D. [x for x in range(5) if x % 2 == 0]答案:D9.以下哪个函数用于计算字符串的长度?A. strlen()B. len()C. sizeof()D. count()答案:B10.以下哪个选项是Java中的错误处理机制?A. try-catchB. if-elseC. for-loopD. while-loop答案:A二、填空题(每题2分,共20分)1.在C语言中,标准输入输出头文件是____。
判断题5 使用关键字class定义的类中默认的访问权限是私有(private)的. 对6 作用域运算符(::)只能用来限定成员函数所属的类. 错7 构造函数和析构函数都不能重载. 错8 析构函数是一种函数体为空的成员函数。
错9 说明或定义对象时,类名前面不需要加class关键字. 对10 对象成员的表示与结构变量成员的表示相同,使用运算符。
或->。
对11 所谓私有成员是指只有类中所提供的成员函数才能直接使用它们,任何类以外的函数对它们的访问都是非法的. 对12 某类中的友元类的所有成员函数可以存取或修改该类中的私有成员。
对13 可以在类的构造函数中对静态数据成员进行初始化. 错14 函数的定义不可以嵌套,类的定义可以嵌套。
对15 C++语言中,既允许单继承,又允许多继承。
对16 派生类是从基类派生出来,它不能再生成新的派生类. 错17 派生类的继承方式中有两种:公有继承和私有继承. 错18 在公有继承中,基类中的公有成员和私有成员在派生类中都是可见的. 错19 在公有继承中,基类中只有公有成员对派生类对象是可见的。
对20 在私有继承中,基类中只有公有成员对派生类是可见的. 错21 在私有继承中,基类中所有成员对派生类的对象都是不可见的。
对22 在保护继承中,对于派生类的访问同于公有继承,而对于派生类的对象的访问同于私有继承。
对23 派生类中至少包含了它的所有基类的成员,在这些成员中可能有的是不可访问. 对24 构造函数可以被继承. 错25 析构函数不能被继承. 对26 子类型是不可逆的. 对27 只要是类M继承了类N,就可以说类M是类N的子类型。
错28 如果A类型是B类型的子类型,则A类型必然适应于B类型. 对29 多继承情况下,派生类的构造函数中基类构造函数的执行顺序取决于定义派生类时所指定的各基类的顺序。
对30 单继承情况下,派生类中对基类成员的访问也会出现二义性. 错31 解决多继承情况下出现的二义性的方法之一是使用成员名限定法. 对32 虚基类是用来解决多继承中公共基类在派生类中只产生一个基类子对象的问题. 对33 指向对象的指针和指向类的成员的指针在表达形式上是不相同的. 对34 已知:m是类A的对象,n是类A的公有数据成员,p是指向类A中n成员的指针.下述两种表示是等价的. m.n和m。
第九章继承与派生类9.2 典型例题解析与解答例题 1:以下对派生类的描述中,()是错误的。
A.一个派生类可以作为另一个派生类的基类B.派生类最少有一个基类C.派生类的成员除了它自己的成员外,还包括了它的基类成员D.派生类中继承的基类成员的接见权限到派生类保持不变答案: D解析:一个派生类可以作为另一个派生类的基类。
无论是单继承还是多继承,派生类最少有一个基类。
派生类的成员除了它自己的成员外,还包括了它的基类成员。
派生类中继承的基类成员的接见权限到派生类受继承方式影响的,关于私有继承,基类的 public , protected 成员在派生类中作为 private 成员;关于公有继承,基类的public , protected 成员在派生类中接见属性不变;关于保护继承,基类的public 、 protected成员在派生类中作为protected成员。
例题 2:派生类的对象对它的哪一类基类成员是可以接见的?()A.公有继承的基类的公有成员 B. 公有继承的基类的保护成员C. 公有继承的基类的私有成员D. 保护继承的基类的公有成员答案: A解析:公有继承的基类的公有成员在派生类中保持公有接见权限,因此派生类对象可以接见它;公有继承的基类的保护成员在派生类中保持保护接见权限,因此派生类对象不行以接见它;基类的私有成员不可以被派生到派生类中,因此派生类对象不可以接见它;保护继承的基类的公有成员在派生类中变为保护的接见权限,因此派生类对象不行以接见它。
例题 3:关于多继承二义性的描述,()是错误的。
A.派生类的多个基类中存在同名成员时,派生类对这个成员接见可能出现二义性B.一个派生类是从拥有共同的间接基类的两个基类派生来的,派生类对该公共基类的接见可能出现二义性C.解决二义性最常用的方法是作用域运算符对成员进行限制D.派生类和它的基类中出现同名函数时,将可能出现二义性答案: D解析:出现二义性有两种状况:调用不一样基类的同样成员时可能出现二义性;接见共同基类的成员时可能出现二义性。
本文作者:黄邦勇帅学习本文首先你应熟悉C++中的构造函数,基本的类的声明及怎样初始化类,关于这些问题,请参看本人所作的《C++构造函数,复制构造函数和析构函数》一文,在这篇文章中作了详细的介绍。
本文分两部分即继承和虚函数与多态性,本文第一部分详细讲解了继承时的构造函数和析构函数的问题,父类与子类的同名变量和函数问题,最后介绍了多重继承与虚基类。
本文第二部分重点介绍了虚函数与多态性的问题,因此学习虚函数的基础是继承,因此在学习虚函数前应学好继承。
本文详细易懂,内容全面,是学习C++的不错的资料。
本文内容完全属于个人见解与参考文现的作者无关,其中难免有误解之处,望指出更正。
声明:禁止抄袭本文,若需要转载本文请注明转载的网址,或者注明转载自“黄邦勇帅”。
主要参考文献:1、C++.Primer.Plus.第五版.中文版[美]Stephen Prata著孙建春韦强译人民邮电出版社2005年5月2、C++.Primer.Plus.第四版.中文版Stanley B.Lippman、Barbara E.Moo著李师贤等译人民邮电出版社2006年3月3、C++.Primer.Plus.第三版.中文版Stanley B.Lippman等著潘爱民张丽译中国电力出版社2002年5月4、C++入门经典第三版[美]Ivor Horton著李予敏译清华大学出版社2006年1月5、C++参考大全第四版[美]Herbert Schidt著周志荣朱德芳于秀山等译电子工业出版社2003年9月6、21天学通第四版C++ [美]Jesse Liberty著康博创作室译人民邮电出版社2002年3月14 继承(基类,父类,超类),派生类,子类一:继承中的访问权限关系。
1.基类,父类,超类是指被继承的类,派生类,子类是指继承于基类的类.2.在C++中使用:冒号表示继承,如class A:public B;表示派生类A从基类B继承而来3.派生类包含基类的所有成员,而且还包括自已特有的成员,派生类和派生类对象访问基类中的成员就像访问自已的成员一样,可以直接使用,不需加任何操作符,但派生类仍然无法访问基类中的私有成员.4.在C++中派生类可以同时从多个基类继承,Java不充许这种多重继承,当继承多个基类时,使用逗号将基类隔开.5.基类访问控制符,class A:public B基类以公有方式被继承,A:private B基类以私有方式被继承,A:protected B基类以受保护方式被继承,如果没有访问控制符则默认为私有继承。
c语言子类调用父类构造函数
c语言中,子类调用父类构造函数,一般采用两种方式:
1. 使用基类构造函数调用:
子类通过声明基类的构造函数,并调用该构造函数,完成父类的构造,被称为使用基类构造函数调用。
这样的优缺点分别:
优点:简单、直观,使用相对简单,效率高,功能强大;
缺点:需要将基类的构造函数的参数准确的传入子类,容易出现参数传入错误或者参数当不凑。
2. 使用继承初始化列表调用:
使用继承初始化列表调用,是指在子类构造函数中,使用冒号将基类构造函数与子类定义相结合,用继承初始化列表完成父类的构造。
这样的优缺点:
优点:不需要手动声明和调用父类的构造函数,使用统一初始化方便;
缺点:父类构造函数只能被调用一次,无法重用,且不能实现多继承。
总之,使用基类构造函数调用比使用继承初始化列表调用有更多的优势,且在实际开发过程中也更加常用。
C++考试题(选择题)1、选择题1、___A__只能访问静态成员变量。
A 静态函数B 虚函数C 构造函数D 析构函数2、下列的各类函数中,__C___不是类的成员函数。
A 构造函数B 析构函数C友元函数 D 拷贝构造函数3、友元的作用_A__。
A 提高程序的运行效率B 加强类的封装性C 实现数据的隐藏性D 增加成员函数的种类4、类模板的使用实际上是将类模板实例化成一个具体的_D____。
A 类B 对象C 函数D 模板类5、下列函数中,___C__不能重载。
A 成员函数B 非成员函数C 析构函数D 构造函数6、___C__是一个在基类中说明的虚函数,它在该基类中没有定义,但要求任何派生类都必须定义自己的版本。
A 虚析构函数B虚构造函数C纯虚函数 D 静态成员函数7、__A___是istream的派生类,处理文件输入;___C__是iostream的派生类,可以同时处理文件的I/O。
A、ifstreamB、ostreamC、fstreamD、ofstream8、对于派生类的构造函数,在定义对象时构造函数的执行顺序为:先执行__A___,再执行__B___,后执行__C___。
A 成员对象的构造函数B 基类的构造函数C 派生类本身的构造函数9、局部变量可以隐藏全局变量,那么在有同名全局变量和局部变量的情形时,可以用__A___提供对全局变量的访问。
A 域运算符B 类运算符C 重载D 引用10、一个__C___允许用户为类定义一种模式,使得类中的某些数据成员及某些成员函数的返回值能取任意类型。
A 函数模板B 模板函数C 类模板D 模板类11、系统在调用重载函数时,往往根据一些条件确定哪个重载函数被调用,在下列选项中,不能作为依据的是___D__。
A 参数个数B 参数的类型C 函数名称D函数的类型12、如果一个类至少有一个纯虚函数,那么就称该类为__A___。
A 抽象类B 虚基类C 派生类D 以上都不对13、进行文件操作时需要包含__B___文件。
基类成员的初始化工作由基类的构造函数完成,派生类的初始化工作则有派生类的构造函数完成,这就产生了派生类构造函数的执行顺序问题,即当创建一个派生类的对象时,如何调用基类和派生类的构造函数分别完成各自成员的初始化。
派生类中的构造函数:如果基类没有定义构造函数,派生类也可以不定义构造函数,全都采用默认的构造函数,此时,派生类新增成员的初始化工作可用其他公有函数来完成,如果只有派生类定义构造函数时,只需构造派生类对象即可。
对象的基类部分使用默认构造函数来自动创建。
基类中的构造函数:当基类和派生类都定义有构造函数时,情况就变得复杂了,同时也存在着继承规则。
1.如果基类中定义了构造函数,并且此构造函数没有参数,那么他可以隐式的被派生类继承,也就是说,派生类根本不需要包含构造函数,如下例子:namespace Syntaxtest{class Personclass{protected Personclass(){Console.WriteLine("基¨´类¤¨¤中D的Ì?构1造¨¬函¡¥数ºy被À?继¨¬承D!ê?");}}class Studentclass : Personclass{}class Program{static void Main(string[] args){Studentclass t1 = new Studentclass();}}}运行结果:在基类中构造函数被继承从运行结果来看,基类没有参数的构造函数被无条件继承,在派生类中被调用。
2.如果基类定义了带有参数的构造函数,则此构造函数必须被继承且在派生类中实现构造函数,提供一个将参数传递给基类构造函数的途径,以保证在基类进行初始化时能获得必须的数据,在实现构造函数时我们可以使用base关键字。
代码如下:namespace Syntaxtest{class Personclass{protected Personclass(string T,string M){Console.WriteLine("基¨´类¤¨¤中D的Ì?构1造¨¬函¡¥数ºy的Ì?内¨²容¨Y!ê?");Console.WriteLine("基¨´类¤¨¤中D的Ì?构1造¨¬函¡¥数ºy被À?继¨¬承D!ê?");Console.WriteLine("传ä?递ÌY的Ì?参?数ºy:{0}",T);Console.WriteLine("传ä?递ÌY的Ì?参?数ºy:{0}",M);}}class Studentclass : Personclass{public Studentclass(string N, string I):base(N,I){Console.WriteLine("派¨¦生¦¨²类¤¨¤中D的Ì?构1造¨¬函¡¥数ºy的Ì?内¨²容¨Y!ê?");Console.WriteLine("参?数ºy设¦¨¨置?的Ì?ID是º?:{0}", I);Console.WriteLine("参?数ºy设¦¨¨置?的Ì?姓?名?是º?:{0}", N);}}class Program{static void Main(string[] args){Studentclass t1 = new Studentclass("xusen","2010");}}运行结果:基¨´类¤¨¤中D的Ì?构1造¨¬函¡¥数ºy的Ì?内¨²容¨Y!ê?基¨´类¤¨¤中D的Ì?构1造¨¬函¡¥数ºy被À?继¨¬承D!ê传递的参数:xusen传递的参数:2010派¨¦生¦¨²类¤¨¤中D的Ì?构1造¨¬函¡¥数ºy的Ì?内¨²容¨Y!ê?参数设置的姓名是:xusen参数设置的ID是:2010派生类隐式继承基类中带有参数的构造函数,在程序中基类定义了带有参数的构造函数,在其派生类中被继承,并使用base关键字调用基类中的构造函数来传送参数。
我们可以从代码中看到在创建派生类的对象后,程序首先运行的是基类的构造函数中的内容,然后才是派生类中的内容。
3.基类中是没有参数的构造函数,在派生类中可以自定义有参数的构造函数如果派生类的基类也是派生类,则每个派生类只需负责其直接基类的构造,不负责间接基类的构造,并且其执行构造函数的顺序是从最上面的基类开始的,直到最后一个派生类结束。
代码如下:namespace Syntaxtest{class Firstclass{protected Firstclass(string A, string B){Console.WriteLine("第̨²一°?个?基¨´类¤¨¤中D的Ì?内¨²容¨Y!ê?");Console.WriteLine("第̨²一°?个?基¨´类¤¨¤中D的Ì?内¨²容¨Y被À?继¨¬承D!ê?");Console.WriteLine("传ä?递ÌY的Ì?参?数ºy:{0}", A);Console.WriteLine("传ä?递ÌY的Ì?参?数ºy:{0}", B);}}class Personclass:Firstclass{protected Personclass(string T,string M):base(T,M){Console.WriteLine("基¨´类¤¨¤中D的Ì?构1造¨¬函¡¥数ºy的Ì?内¨²容¨Y!ê?");Console.WriteLine("基¨´类¤¨¤中D的Ì?构1造¨¬函¡¥数ºy被À?继¨¬承D!ê?");Console.WriteLine("传ä?递ÌY的Ì?参?数ºy:{0}",T);Console.WriteLine("传ä?递ÌY的Ì?参?数ºy:{0}",M);}}class Studentclass : Personclass{public Studentclass(string N, string I):base(N,I){Console.WriteLine("派¨¦生¦¨²类¤¨¤中D的Ì?构1造¨¬函¡¥数ºy的Ì?内¨²容¨Y!ê?");Console.WriteLine("参?数ºy设¦¨¨置?的Ì?ID是º?:{0}", I);Console.WriteLine("参?数ºy设¦¨¨置?的Ì?姓?名?是º?:{0}", N);}}class Program{static void Main(string[] args){Studentclass t1 = new Studentclass("xusen","2010");}}}运行结果:第一个基类中的内容第一个基类中的内容被继承传递的参数:xusen传递的参数:2010基¨´类¤¨¤中D的Ì?构1造¨¬函¡¥数ºy的Ì?内¨²容¨Y!ê?基¨´类¤¨¤中D的Ì?构1造¨¬函¡¥数ºy被À?继¨¬承D!ê传递的参数:xusen传递的参数:2010派¨¦生¦¨²类¤¨¤中D的Ì?构1造¨¬函¡¥数ºy的Ì?内¨²容¨Y!ê?参数设置的姓名是:xusen参数设置的ID是:2010。