在名字空间中声明类和成员函数
C++类的声明和对象的定义

C++类的声明和对象的定义⼀、类和对象的关系每⼀个实体都是对象。
有⼀些对象是具有相同的结构和特性的。
每个对象都属于⼀个特定的类型。
在C++中对象的类型称为类(class )。
类代表了某⼀批对象的共性和特征。
前⾯已说明:类是对象的抽象,⽽对象是类的具体实例(instance)。
正如同结构体类型和结构体变量的关系⼀样,⼈们先声明⼀个结构体类型,然后⽤它去定义结构体变量。
同⼀个结构体类型可以定义出多个不同的结构体变量。
在C++中也是先声明⼀个类类型,然后⽤它去定义若⼲个同类型的对象。
对象就是类类型的⼀个变量。
可以说类是对象的模板,是⽤来定义对象的⼀种抽象类型。
类是抽象的,不占⽤内存,⽽对象是具体的,占⽤存储空间。
在⼀开始时弄清对象和类的关系是⼗分重要的。
⼆、声明类类型类是⽤户⾃⼰指定的类型。
如果程序中要⽤到类类型,必须⾃⼰根据需要进⾏声明,或者使⽤别⼈已设计好的类。
C++标准本⾝并不提供现成的类的名称、结构和内容。
在C++中声明⼀个类类型和声明⼀个结构体类型是相似的。
下⾯是声明⼀个结构体类型的⽅法: struct Student //声明了⼀个名为Student的结构体类型 { int num; char name[20]; char sex; }; Student stud1,stud2; //定义了两个结构体变量stud1和stud2,它只包括数据,没有包括操作。
现在声明⼀个类: class Student //以class开头 { int num; char name[20]; char sex;//以上3⾏是数据成员 void display( ) //这是成员函数 { cout<<″num:″<<num<<endl; cout<<″name:″<<name<<endl; cout<<″sex:″<<sex<<endl; //以上4⾏是函数中的操作语句} };Student stud1,stud2;//定义了两个Student 类的对象stud1和stud2 } 可以看到声明类的⽅法是由声明结构体类型的⽅法发展⽽来的。
C++operator关键字(重载操作符)

C++operator关键字(重载操作符)operator是C++的关键字,它和运算符⼀起使⽤,表⽰⼀个运算符函数,理解时应将operator=整体上视为⼀个函数名。
这是C++扩展运算符功能的⽅法,虽然样⼦古怪,但也可以理解:⼀⽅⾯要使运算符的使⽤⽅法与其原来⼀致,另⼀⽅⾯扩展其功能只能通过函数的⽅式(c++中,“功能”都是由函数实现的)。
⼀、为什么使⽤操作符重载?对于系统的所有操作符,⼀般情况下,只⽀持基本数据类型和标准库中提供的class,对于⽤户⾃⼰定义的class,如果想⽀持基本操作,⽐如⽐较⼤⼩,判断是否相等,等等,则需要⽤户⾃⼰来定义关于这个操作符的具体实现。
⽐如,判断两个⼈是否⼀样⼤,我们默认的规则是按照其年龄来⽐较,所以,在设计person 这个class的时候,我们需要考虑操作符==,⽽且,根据刚才的分析,⽐较的依据应该是age。
那么为什么叫重载呢?这是因为,在编译器实现的时候,已经为我们提供了这个操作符的基本数据类型实现版本,但是现在他的操作数变成了⽤户定义的数据类型class,所以,需要⽤户⾃⼰来提供该参数版本的实现。
⼆、如何声明⼀个重载的操作符?A: 操作符重载实现为类成员函数重载的操作符在类体中被声明,声明⽅式如同普通成员函数⼀样,只不过他的名字包含关键字operator,以及紧跟其后的⼀个c++预定义的操作符。
可以⽤如下的⽅式来声明⼀个预定义的==操作符:class person{private:int age;public:person(int a){this->age=a;}inline bool operator == (const person &ps) const;};实现⽅式如下:inline bool person::operator==(const person &ps) const{if (this->age==ps.age)return true;return false;}调⽤⽅式如下:#includeusing namespace std;int main(){person p1(10);person p2(20);if(p1==p2) cout<<”the age is equal!”< return 0;}这⾥,因为operator ==是class person的⼀个成员函数,所以对象p1,p2都可以调⽤该函数,上⾯的if语句中,相当于p1调⽤函数==,把p2作为该函数的⼀个参数传递给该函数,从⽽实现了两个对象的⽐较。
C++文档

下面例子是将一个文件的内容拷贝到另一个文件:
void main() {
cout << "Hello, World! I am " << 8 << " Today!" << endl;
} 例1
通过“<<”操作符把一系列的参数传递给 cout 对象。然后 cout 对象按从左向右的顺序 将参数打印出来。输入输出流函数 endl 表示一行结束并在行末加上一个换行符。使用输入 输出流,可将一系列的参数按顺序排起来,使类易于使用。
2.2 读取输入数据
//Converts decimal to octal and hex #include <iostream> using namespace std;
void main() {
int number; cout << "Enter a decimal number: "; cin >> number;
#include <iostream.h> 它相当于 #include <iostream> using namespace std;
第 2 章 简单的 C++程序的例子
下面给出几个简单的 C++程序的例子,让我们浅尝一下 C++的“味道”。
(完整版)C++学习笔记

endl换行符,也是std成员函数4).io流运算cout控制台输出—屏幕上终端窗口,带缓冲<<插入运算符cin控制台输入—键盘>>提取运算符5).名字空间Std:标准c++库所提供一切函数、对象、类型都隶属于std名字空间。
::-作用域限定符---名字空间“的”某个对象。
+= -=名字冲突:看作用域。
同一作用域不可使用相同名字。
----解决方法:成员前加名字空间名,中间::3.名字空间namespace 名字空间名{名字空间成员1;名字空间成员2;//名字空间成员可以是变量、函数、类型}名字空间名::名字空间成员1名字空间合并:同一个名字空间可以分别书写在不同的namespace子句中,只要它们的名字相同,仍然会被编译器识别为同一个名字空间。
Namespace名字空间名{名字空间成员1;}namespace名字空间名{名字空间成员2;}名字空间成员的声明和定义可以分开写,但是定义部分需要借助作用域限定符“::”指明所定义的成员隶属于哪个名字空间。
名字空间指令:using namespace名字空间名;名字空间指令以后的代码,对名字空间中的所有成员可见,可以直接引用,无需作用域限定符。
使用时要注意不要引入新的名字冲突。
名字空间声明:using名字空间名::名字空间成员;名字空间声明用于将名字空间中的特定标识符引入当前作用域,可以省略作用域限定符,直接引用之。
使用时注意不要因此引入新的名字冲突。
无名名字空间:不隶属于任何名字空间的标识符,编译器就将其缺省地放入无名名字空间。
对于无名名字空间中的成员,可以直接使用“::”进行访问。
名字空间允许多层嵌套,访问时需要逐层分解。
可利用名字空间别名简化名字空间嵌套路径的书写形式。
Using只能看里面一层。
4.结构、联合和枚举1)所有的类型关键字在声明变量时都可以省略。
struct Date{ //Date结构名int year; //成员变量(成员表列)(类型说明符成员名)int month;int day;void show(void)//成员函数{}};Int main(void){ //全局变量Date d = {2016,8,2},*e = &d;//e是指向d的指针d.show(); //“.”直接成员访问运算符e->show (); //“->”间接成员访问运算符return 0;}struct Date d = {2016,8,2};//C/C++Date d = {2016,8,2};//C++ //类型关键字省略2)C++中结构体可以包含函数(一个int四个字节,函数不放变量中,放代码区)成员函数的调用,前面要写“.”“->”定义结构体时不能同时初始化!3)C++中增加了匿名联合。
复习题汇总

面向对象程序设计课程复习题一、判断题1. 程序的编译是以文件为单位的,因此将程序分到多个文件中可以减少每次对程序修改所带来的编译工作量。
2. 派生类的成员函数可以直接访问基类的所有成员。
3. 函数的参数和返回值类型可以是简单数据类型,也可以是指针、引用、数组和类。
4. 如果派生类的成员函数的原型与基类中被定义为虚函数的成员函数原型相同,那么,这个函数自动继承基类中虚函数的特性。
5. 函数重载既要求两函数参数对应的类型不同又要求参数个数不同。
6.字符串”hello,world”在内存中存放时,占用11个字节的空间7.当函数的返回值是数组类型的,传递的是数组第一个元素的地址。
8.在内存中,一个字符常量或变量是以ASCII码值存储的,它可直接作为整数值参加运算。
1、√2、X3、X4、√5、X6、X7、√8、√1.在C++中,也可使用struct来声明类,但在该类中不能声明成员函数。
(X )2.在定义二维数组时,语句“int a[][4]={{1,2,3},{4}};”是不正确的。
(X )3.采用inline 定义内联函数时,在对于函数代码少、频繁调用的情况下特别有效。
(V )4.类中的静态成员数据为该类的所有对象所共享,并且,在该类对象被撤销时,静态成员并没有撤销。
(V )5.构造函数和析构函数均不能被说明为虚函数。
(X )6.char *const p 表明p是一个指针,它只能指向一个字符串常量。
(X )7.如果派生类的继承方式是protected的,则在main( )函数中,可以通过派生类对象来访问基类的公有的成员。
(X )8.在C++中,可以通过ofstream类对象来建立一个输出文件流。
(V )9.在C语言中,不使用命名空间,但在C++程序中,一定要使用命名空间。
(X )10.在MFC编程中,通过Invalidate(TRUE)可以发出重绘视图的消息。
(V )1 2 3 4 5 6 7 8 9 10××√√×××√×√1.C++程序总是从第一个定义的函数开始执行。
C++模板详解(一)

C++模板详解(⼀)C++模板 模板是C++⽀持参数化多态的⼯具,使⽤模板可以使⽤户为类或者函数声明⼀种⼀般模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型。
模板是⼀种对类型进⾏参数化的⼯具; 通常有两种形式:函数模板和类模板; 函数模板针对仅参数类型不同的函数; 类模板针对仅数据成员和成员函数类型不同的类。
使⽤模板的⽬的就是能够让程序员编写与类型⽆关的代码。
⽐如编写了⼀个交换两个整型int 类型的swap函数,这个函数就只能实现int 型,对double,字符这些类型⽆法实现,要实现这些类型的交换就要重新编写另⼀个swap函数。
使⽤模板的⽬的就是要让这程序的实现与类型⽆关,⽐如⼀个swap模板函数,即可以实现int 型,⼜可以实现double型的交换。
模板可以应⽤于函数和类。
下⾯分别介绍。
注意:模板的声明或定义只能在全局,命名空间或类范围内进⾏。
即不能在局部范围,函数内进⾏,⽐如不能在main函数中声明或定义⼀个模板。
⼀、函数模板通式1、函数模板的格式: template <class形参名,class形参名,......> 返回类型函数名(参数列表) { 函数体 } 其中template和class是关见字,class可以⽤typename 关见字代替,在这⾥typename 和class没区别,<>括号中的参数叫模板形参,模板形参和函数形参很相像,模板形参不能为空。
⼀但声明了模板函数就可以⽤模板函数的形参名声明类中的成员变量和成员函数,即可以在该函数中使⽤内置类型的地⽅都可以使⽤模板形参名。
模板形参需要调⽤该模板函数时提供的模板实参来初始化模板形参,⼀旦编译器确定了实际的模板实参类型就称他实例化了函数模板的⼀个实例。
⽐如swap的模板函数形式为 template <class T> void swap(T& a, T& b){},当调⽤这样的模板函数时类型T就会被被调⽤时的类型所代替,⽐如swap(a,b)其中a和b是int 型,这时模板函数swap中的形参T就会被int 所代替,模板函数就变为swap(int &a, int &b)。
面向对象程序设计习题-填空
面向对象程序设计习题-填空题1.在计算机中书写C++语言程序需要用到(编辑器)程序。
2.(链接程序)将编译器输出和各种库函数结合起来,可产生可执行程序。
3.C++语言是面向(对象)的语言。
4.C语言是广为人知的(UNIX )操作系统语言。
5.唯一能让计算机直接理解的语言称为计算机的(机器语言)。
6.面向结构的程序设计方法主要由以下3种逻辑结构组成:顺序结构、(循环结构)和(选择结构)。
7.面向对象的程序设计达到了软件工程的3个目标,即(重用性)、灵活性和扩展性。
8.面向对象系统最主要的特性是(封装性)、(继承性)和多态性。
9.(继承)机制为程序提供了一种组织、构造和重用类的手段。
10.(多态)指对象接收到不同消息时产生不同的行为方式。
11.每一个C++语言程序从(main )函数处开始执行。
12.每个函数体从({)开始,从(})结束。
13.每个C++语言语句以(; )结束。
14.(cin )对象通过键盘输入值。
15.(// )用于为程序做单行注解,提高程序的可读性。
16.(cout )用于在屏幕上打印信息。
17.C++语言使用运算符“<<”和“>>”分别实现(输入)和(输出)。
18.预处理器指令以(# )符号开头。
19.标准命名空间可以简写成为(std )。
20.为了使用C++语言的标准字符串类,必须要包含头文件(string )。
21.布尔型是最简单的数据类型,它有两种表示形式:(true )和(false )。
22.声明枚举的关键字是(enum )。
23.C++语言的数据类型十分丰富,包括基本数据类型、(派生类型)和(类类型)。
24.按照存储空间,整型又可分为短整型、(整型)和(长整型)。
25.C++语言中的(sizeof )运算符,可以用来计算一个特定对象或类型存储时需要的字节数。
26.浮点类型取值范围的定义包含在标准头文件(climits )中。
27.在程序运行过程中,有些值会保持不变,称之为(常量)。
C命名空间namespace的作用和使用解析
C命名空间namespace的作用和使用解析一、为什么需要命名空间(问题提出)命名空间是ANSIC++引入的可以由用户命名的作用域,用来处理程序中常见的同名冲突。
在 C语言中定义了3个层次的作用域,即文件(编译单元)、函数和复合语句。
C++又引入了类作用域,类是出现在文件内的。
在不同的作用域中可以定义相同名字的变量,互不于扰,系统能够区别它们。
1、全局变量的作用域是整个程序,在同一作用域中不应有两个或多个同名的实体(enuty),包括变量、函数和类等。
例:如果在文件中定义了两个类,在这两个类中可以有同名的函数。
在引用时,为了区别,应该加上类名作为限定:class A //声明A类{ public:void funl();//声明A类中的funl函数private:int i; };void A::funl() //定义A类中的funl函数{…………}class B //声明B类{ public: void funl(); //B类中也有funl函数 void fun2(); };void B::funl() //定义B类中的funl函数{ …………}这样不会发生混淆。
在文件中可以定义全局变量(global variable),它的作用域是整个程序。
如果在文件A中定义了一个变量a int a=3;在文件B中可以再定义一个变量a int a=5;在分别对文件A和文件B进行编译时不会有问题。
但是,如果一个程序包括文件A和文件B,那么在进行连接时,会报告出错,因为在同一个程序中有两个同名的变量,认为是对变量的重复定义。
可以通过extern声明同一程序中的两个文件中的同名变量是同一个变量。
如果在文件B中有以下声明:extem int a;表示文件B中的变量a是在其他文件中已定义的变量。
由于有此声明,在程序编译和连接后,文件A的变量a的作用域扩展到了文件B。
如果在文件B中不再对a赋值,则在文件B中用以下语句输出的是文件A中变量a的值: cout<二、什么是命名空间(解决方案)命名空间:实际上就是一个由程序设计者命名的内存区域,程序设计者可以根据需要指定一些有名字的空间域,把一些全局实体分别放在各个命名空间中,从而与其他全局实体分隔开来。
为什么需要命名空间
3:为什么需要命名空间一、为什么需要命名空间(问题提出)命名空间是ANSIC++引入的可以由用户命名的作用域,用来处理程序中常见的同名冲突。
在C语言中定义了3个层次的作用域,即文件(编译单元)、函数和复合语句。
C++又引入了类作用域,类是出现在文件内的。
在不同的作用域中可以定义相同名字的变量,互不于扰,系统能够区别它们。
1、全局变量的作用域是整个程序,在同一作用域中不应有两个或多个同名的实体(enuty),包括变量、函数和类等。
例:如果在文件中定义了两个类,在这两个类中可以有同名的函数。
在引用时,为了区别,应该加上类名作为限定:class A //声明A类{ public:void funl();//声明A类中的funl函数private:int i; };void A::funl() //定义A类中的funl函数{…………}class B //声明B类{ public:void funl(); //B类中也有funl函数void fun2(); };void B::funl() //定义B类中的funl函数{ …………}这样不会发生混淆。
在文件中可以定义全局变量(global variable),它的作用域是整个程序。
如果在文件A中定义了一个变量a int a=3;在文件B中可以再定义一个变量a int a=5;在分别对文件A和文件B进行编译时不会有问题。
但是,如果一个程序包括文件A和文件B,那么在进行连接时,会报告出错,因为在同一个程序中有两个同名的变量,认为是对变量的重复定义。
可以通过extern声明同一程序中的两个文件中的同名变量是同一个变量。
如果在文件B中有以下声明:extem int a;表示文件B中的变量a是在其他文件中已定义的变量。
由于有此声明,在程序编译和连接后,文件A的变量a的作用域扩展到了文件B。
如果在文件B中不再对a赋值,则在文件B中用以下语句输出的是文件A中变量a的值: cout<<a; //得到a的值为32、程序中就会出现名字冲突。
C++知识点总结
类和对象初步1.类的定义在定义外成员函数的实现2.类的成员函数之间可以相互调用,类的成员函数也可以重载,也可设默认参数值3.一般来讲,一个对象占用的内存空间的大小等于其成员变量的体积之和。
每个对象都有自己的存储空间(成员变量),但成员函数只有一份对象名.成员名指针->成员名引用名.成员名4.private:一个类的私有成员,只能在该类的成员函数中才能访问public:proteced:5.class默认private struct默认public6.内联成员函数:成员函数名前加inline 或函数体写在类定义内部的成员函数。
执行更快,但会带来额外的内存开销构造函数1.构造函数全局变量在堆上,系统自动初始化为零。
局部变量在栈上,初始值是随机的,需要初始化。
2.构造函数:对对象进行初始化。
构造函数执行时对象的内存空间已经分配,构造函数的作用是初始化这片空间.可重载,不写的话有默认构造函数,但是如果编写了构造函数,那默认构造函数不会再执行.是一类特殊的成员函数。
不写返回值类型,函数名为类名.3.对象在生成时一定会调用某个构造函数,一旦生成,不再执行构造函数.4.P183 Ctest *pArray[3]={new Ctest(4),new Ctest(1,2)}5.复制构造函数:其是构造函数的一种,只有一个参数,为本类的引用,防止混淆,构造函数不能以本类的对象作为唯一的参数。
默认复制构造函数。
6.复制构造函数被调用的三种情形:1用一个对象去初始化另一个对象时Complex C1(C2)ComplexC2=C1; 2 函数的参数是类A的对象。
形参未必等于实参函数中用对象的引用不会调用复制构造函数void Function(const Complex &c)3 函数的返回值是类A的对象7.类型转换构造函数:除复制构造函数外,只有一个参数的构造函数C=68.析构函数:在对象消亡时调用,可以定义其做善后工作。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
在名字空间中声明类和成员函数
赵湘宁
虽然很多程序员都熟悉名字空间的概念,但他们常常都是被动地使用名字空间。
也就是说他们使用的是第三方定义的成员(如标准库的类和函数),而不是在名字空间中声明自己的类和函数。
本文拟讨论如何在名字空间中声明自己的类和函数,以及如何在程序中使用它们。
名字空间是一个范畴,它包含类声明,函数声明,常量声明和模板声明等名字空间成员。
例如:
namespace proj_alpha
{
//下面是名字空间proj_alpha 的成员
class Spy {/*..*/};
void encrypt (char *msg);
const int MAX_SPIES = 8;
}
在上面的例子中,类Spy在一个单独的文件中实现。
通常,你是在一个专门的头文件中声明一个类并在不同的源文件中独立地定义其成员函数。
那么如何将名字空间成员类分离成多个源文件呢?
下面是名为Foo.hpp 的头文件,其中定义了一个名为NS的名字空间,它包含类Foo的声明:
//Foo.hpp
namespace NS
{
class Foo
{
public:
void f();
void g();
};
}//close NS
另外,在一个单独的源文件Foo.cpp中,首先包含头文件Foo.hpp以便实现类Foo的成员函数f()和g():
//Foo.cpp
#include "Foo.hpp"
void NS::Foo::f()
{ /*..*/ }
void NS::Foo::g()
{ /*..*/ }
为了使用名字空间成员,必须使用成员的全路径名,它由名字空间后跟::合成原名组成。
因此,类Foo的全路径名是NS::Foo。
这样编译器便可以知道NS是一个名字空间名,头文件Foo.hpp必须在引用NS之前被包含。
名字空间是可以扩展的。
也就是说可以声明类,而且所声明的类在其它的.cpp文件中是相同的名字空间成员:
//Bar.hpp
namespace NS //扩展NS
{
class Bar
{
public:
void a();
void b();
};
}
在Bar.cpp文件中:
#include "Bar.hpp"
void NS::Bar::a()
{/*..*/}
void NS::Bar::b()
{/*..*/}
可以看出,虽然Foo和Bar这两个类在不同的头文件中声明,但它们都是名字空间NS的成员。
并且编译器和链接器将这两个类看成是同一名字空间的成员。
那么,如何在应用程序中使用这些类呢?
在文件main.cpp中,必须要包含声明类Foo和Bar的头文件并加上相应的名字空间引用声明-using:
#include "Bar.hpp"
#include "Foo.hpp"
int main()
{
using NS::Bar; //使用名字空间
using NS::Foo; //同上
Bar b;
Foo f;
f.f();
//...
}
using声明由关键字using后跟名字空间成员的全路径。
这样就使你在using声明范围内使用成员时不用再加路径。
上面的例子中,可以直接使用Foo和Bar,因为在main()的开始使用了using声明。
如果没有using 声明就必须使用全路径成员名。
int main()
{
NS::Bar b; //全路径名
NS::Foo f; //同上
//?
}
另外,还有一种引用名字空间成员的方法是使用using指令:
#include "Bar.hpp"
#include "Foo.hpp"
int main()
{
using namespace NS; // using 指令
Bar b;
Foo f;
f.f();
//...
}
using指令由关键字“using namespace”后跟名字空间名构成。
在访问名字空间成员时它是使用最少的一种方法,原因是这种方法将所有名字空间成员注入当前的范围,从而增加了潜在的名字冲突。