类与对象实验报告C_第1页
类与对象实验报告C_第2页
类与对象实验报告C_第3页
类与对象实验报告C_第4页
类与对象实验报告C_第5页
已阅读5页,还剩75页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

类与对象实验报告(C++)实验内容1.需要求3个长方柱的体积,请编写一个基于对象的程序。数据成员包括length(长)、width(宽)、height(高)。要求用成员函数实现以下功能:(1)由键盘分别输入3个长方柱的长、宽、高。(2)计算长方柱的体积;(3)输出3个长方柱的体积。请编写程序,上机调试并运行。2.建立一个对象数组,内放5个学生的数据(学号、成绩),用指针指向数组首元素,输出第1,3,5学生的数据。3.建立一个对象数组,内放5个学生的数据(学号、成绩),设立一个函数max,用指向对象的指针作函数参数,在max函数中找出5个学生中成绩最高者,并输出其学号。4.修改第6题程序,增加一个fun函数,改写main函数。改为在fun函数中调用change和display函数。在fun函数中使用对象的引用(Student&)作形参。5.商店销售某一商品,每天公布统一的折扣(discount)。同时允许销售人员在销售时灵活掌握售价(price),在此基础上,一次购10件以上者,还可以享受9.8折优惠。现已知当天3个销货员销售情况为销货员号(num)销货件数(quantity)销货单价(price)101523.51021224.5610310021.5请编写程序,计算出当日此商品的总销售款sum以及每件商品的平均售价。要求用静态数据成员和静态成员函数。(提示:将折扣discount,总销售款sum和商品销售总件数n声明为静态数据成员,再定义静态成员函数average(求平均售价)和display(输出结果)。实验答案1.#include<iostream>usingnamespacestd;classa{public:intlength,width,height;voidv(){intv=length*width*height;cout<<"长方体体积为"<<v<<endl;}};intmain(){av1;av2;av3;cout<<"输入第一个长方体的长宽高"<<endl;cin>>v1.length>>v1.width>>v1.height;cout<<"输入第二个长方体的长宽高"<<endl;cin>>v2.length>>v2.width>>v2.height;cout<<"输入第三个长方体的长宽高"<<endl;cin>>v3.length>>v3.width>>v3.height;v1.v();v2.v();v3.v();return0;}2.#include<iostream>usingnamespacestd;classstudent{public:student(intn,floats):num(n),score(s){}voiddisplay(){cout<<num<<""<<score<<endl;}private:intnum,score;};intmain(){studentstud[5]={student(101,99),student(102,85),student(103,76),student(104,90),student(105,66)};student*p=stud;for(inti=0;i<=2;p=p+2,i++)p->display();return0;}3.#include<iostream>#include<string>usingnamespacestd;classStudent{public:Student(intn,intm){num=n;score=m;}voiddisplay();floatscore;intnum;};voidStudent::display(){std::cout<<num<<""<<score<<std::endl;}floatmax(Student*a);intmain(){Studentstud[5]={Student(1,78.5),Student(2,85.5),Student(3,98.5),Student(4,100),Student(5,95.5)};Student*p;p=stud;for(p=stud;p<stud+5;p++){p->display();}Student*p1;p1=stud;max(p1);}floatmax(Student*a){inti,k;floatmax;max=a[0].score;for(i=0;i<5;i++)if(a[i].score>max){max=a[i].score;k=i+1;}std::cout<<"最高分为:"<<max<<""<<"其学号为:"<<k<<std::endl;}4.#include<iostream>#include<string>usingnamespacestd;classStudent{public:Student(intn,floats):num(n),score(s){}voidchange(intn,floats){num=n;score=s;}voiddisplay(){cout<<num<<""<<score<<endl;}private:intnum;floatscore;};voidfun(Student&ss){ss.display();ss.change(101,80.5);ss.display();}intmain(){Studentstud(101,78.5);fun(stud);return0;}5.#include<iostream>usingnamespacestd;classSale{public:Sale(intn,intq,doublepri):num(n),qua(q),price(pri){}staticdoubleaverage(Sale*,intn);staticvoiddisplay(Sale*,intn);private:intnum;intqua;doubleprice;staticdoublediscount;staticdoublesum;staticintcount;};doubleSale::discount=0.98;doubleSale::sum=0;intSale::count=0;doubleSale::average(Sale*cc,intn){Sale*p;for(p=cc;p<cc+n;p++){if(p->qua>10)p->price=p->price*discount;sum=sum+((p->price)*(p->qua));count=count+p->qua;}returnsum/count;}voidSale::display(Sale*cc,intn){cout<<"Average="<<Sale::average(cc,n)<<endl;cout<<"Sum="<<Sale::sum<<endl;}intmain(){Sales[3]={Sale(101,5,23.5),Sale(102,12,24.56),Sale(103,100,21.5)};Sale::display(s,3);return0;}

C++——类与对象简述C++是一种支持面向对象编程的编程语言。在C++中,类和对象是面向对象编程的核心概念。本文将详细介绍C++类和对象的所有内容,包括定义类、创建对象、成员函数、访问控制、构造函数、析构函数等,同时提供代码示例和注意事项。类与对象定义类在C++中,类是一种用户自定义的数据类型。类定义了一个对象的属性和行为,是实现面向对象编程的基本单元。类定义的一般形式如下:class

类名

{

private:

//

私有成员变量和函数

public:

//

公有成员变量和函数

protected:

//

保护成员变量和函数

};在C++中,类的访问控制符有三种,分别是:public、protected和private。这些访问控制符定义了在类的外部如何访问类的成员变量和成员函数。public:public关键字用于指定公共成员。公共成员可以在类的内部和外部进行访问。这意味着,任何一个函数都可以访问公共成员,而不需要进行任何特殊的访问限制。protected:protected关键字用于指定保护成员。保护成员可以在类的内部和派生类中进行访问,但不能在类的外部进行访问。这意味着,只有在派生类中,才能访问保护成员,但在其他任何地方都无法访问。private:private关键字用于指定私有成员。私有成员只能在类的内部进行访问。这意味着,除了类本身以外,没有任何其他函数或类可以访问私有成员。注意事项访问控制符只对类的外部进行限制,而对类的内部则没有任何限制。这意味着,类的成员函数可以访问类的任何成员变量和成员函数,而不需要进行任何特殊的访问限制。公共成员的例子:class

Person

{

public:

std::string

name;

//

公共成员变量

void

setName(std::string

name)

{

this->name

=

name;

}

//

公共成员函数

};

int

main()

{

Person

p;

p.setName("Tom");

//

可以直接访问公共成员

std::cout

<<

<<

std::endl;

//

可以直接访问公共成员

return

0;

}在这个例子中,Person类的name成员变量和setName成员函数都是公共成员。因此,在main函数中,我们可以直接访问p对象的name成员变量和setName成员函数,而不需要进行任何特殊的访问限制。保护成员的例子:class

Person

{

protected:

int

age;

//

保护成员变量

void

setAge(int

age)

{

this->age

=

age;

}

//

保护成员函数

};

class

Student

:

public

Person

{

public:

void

setStudentAge(int

age)

{

setAge(age);

//

可以访问基类的保护成员函数

}

};

int

main()

{

Student

s;

s.setStudentAge(20);

//

可以访问基类的保护成员函数

return

0;

}在这个例子中,Person类的age成员变量和setAge成员函数都是保护成员,它们只能在类内部和派生类中进行访问。在Student类中,我们通过公共成员函数setStudentAge间接地访问了基类Person的保护成员函数setAge,从而实现了对age成员变量的设置。私有成员的例子:class

Person

{

private:

std::string

name;

//

私有成员变量

public:

void

setName(std::string

name)

{

this->name

=

name;

}

//

公共成员函数

std::string

getName()

{

return

name;

}

//

公共成员函数

};

int

main()

{

Person

p;

p.setName("Tom");

//

可以通过公共成员函数访问私有成员

std::cout

<<

p.getName()

<<

std::endl;

//

可以通过公共成员函数访问私有成员

std::cout

<<

<<

std::endl;

//

无法直接访问私有成员

return

0;

}在这个例子中,Person类的name成员变量是私有成员,它只能在类的内部进行访问。在main函数中,我们通过公共成员函数setName和getName来间接地访问name成员变量,而无法直接访问它。创建对象在C++中,对象是类的实例。通过创建对象,可以访问类的成员变量和成员函数。创建对象的一般形式如下://类名

对象名;例如,使用上述Person类创建一个对象的代码如下:

Person

p;在创建对象之后,可以通过对象名访问类的成员变量和成员函数。例如,使用setName和setAge函数设置私有成员变量的值,使用print函数打印私有成员变量的值的代码如下:

Person

p;

p.setName("Tom");

//

输出内容Tom成员函数在C++中,类的成员函数是定义在类内部的函数,用于实现类的行为。成员函数可以访问类的成员变量和成员函数,以及传递参数和返回值。class

Person

{

private:

std::string

name;

//

私有成员变量

public:

void

setName(std::string

name)

//

成员函数

{

this->name

=

name;

}

//

公共成员函数

std::string

getName()

{

return

name;

}

//

公共成员函数

};从上面可知:子类要访问父类中的保护变量、私有变量需要通过公共的成员函数访问,如果公共的成员函数中没有保护·私有变量的内容则不能访问。析构函数在C++中,析构函数是一种特殊的成员函数,用于销毁对象时清理资源。析构函数的名称与类名相同,但前面加上一个波浪号~,没有参数,也不需要显式调用。~类名()

{

//

析构函数体

}下面的Person类添加一个析构函数,用于清理对象的代码如下:class

Person

{

private:

string

name;

int

age;

public:

Person(string

n,

int

a)

{

name

=

n;

age

=

a;

}

~Person()

{

cout

<<

"Destroying

object

"

<<

name

<<

endl;

}

void

setName(string

n)

{

name

=

n;

}

void

setAge(int

a)

{

age

=

a;

}

void

print()

{

cout

<<

"Name:

"

<<

name

<<

endl;

cout

<<

"Age:

"

<<

age

<<

endl;

}

};该析构函数在销毁对象时输出一条消息。例如,销毁上述Person对象的代码如下:Person

p("Tom",

20);

p.print();

//

销毁对象输出结果为:Name:

Tom

Age:

20

Destroying

object

Tom构造函数在C++中,构造函数是一种特殊的成员函数,用于初始化对象的成员变量。构造函数的名称与类名相同,没有返回值类型,也不需要显式调用。构造函数的一般形式如下:类名(参数列表)

{

//

构造函数体

}例如,为上述Person类添加一个构造函数,用于初始化name和age成员变量的代码如下:class

Person

{

private:

string

name;

int

age;

public:

Person(string

n,

int

a)

{

name

=

n;

age

=

a;

}

void

setName(string

n)

{

name

=

n;

}

void

setAge(int

a)

{

age

=

a;

}

void

print()

{

cout

<<

"Name:

"

<<

name

<<

endl;

cout

<<

"Age:

"

<<

age

<<

endl;

}

};该构造函数接受两个参数n和a,用于初始化name和age成员变量。例如,使用该构造函数创建一个Person对象的代码如下:Person

p("Tom",

20);

p.print();输出结果为:Name:

Tom

Age:

20静态成员在C++中,静态成员是类的成员,但不属于任何对象。静态成员可以被类的所有对象共享,也可以通过类名直接访问。静态成员可以是静态数据成员或静态成员函数。静态数据成员是指属于类的变量,静态成员函数是指属于类的函数。静态数据成员的声明和定义必须在类的外部进行,并且要在前面加上关键字static。例如,为上述Person类添加一个静态数据成员count,用于记录创建的Person对象数量的代码如下:class

Person

{

private:

string

name;

int

age;

static

int

count;

//

静态数据成员

public:

Person(string

n,

int

a)

{

name

=

n;

age

=

a;

count++;

//

每次创建对象时增加对象数量

}

~Person()

{

count--;

//

每次销毁对象时减少对象数量

}

void

setName(string

n)

{

name

=

n;

}

void

setAge(int

a)

{

age

=

a;

}

void

print()

{

cout

<<

"Name:

"

<<

name

<<

endl;

cout

<<

"Age:

"

<<

age

<<

endl;

}

static

int

getCount()

//

静态成员函数

{

return

count;

}

};

int

Person::count

=

0;

//

静态数据成员的定义例如,使用该类创建三个对象并输出对象数量的代码如下:Person

p1("Tom",20);

Person

p2("Jerry",

18);

Person

p3("Mary",

22);

cout

<<

"Object

count:

"

<<

Person::getCount()

<<

endl;

输出结果Object

count:

3注意事项类的定义必须在使用之前。类的成员变量和成员函数的访问权限必须正确定义,遵循信息隐藏原则。类的成员函数可以直接访问类的成员变量和静态成员,但不能直接访问非静态成员函数。构造函数和析构函数是必须的,用于初始化和清理对象。在创建对象时,如果没有显式地调用构造函数,将调用默认构造函数。如果不需要复制对象,可以将复制构造函数和赋值运算符函数声明为私有,并不实现它们。在使用静态成员时,可以通过类名直接访问,也可以通过对象访问。但访问权限必须正确设置。class与struct的区别与class非常相似的就是C语言中的struct了。structstruct是一种自定义数据类型,可以包含数据成员和函数成员。它的默认访问权限是public,默认的继承方式是public,默认成员类型是public。struct

Point

{

int

x;

int

y;

void

print()

{

cout

<<

"("

<<

x

<<

",

"

<<

y

<<

")"

<<

endl;

}

};上面的代码定义了一个Point结构体,它包含了两个int类型的数据成员x和y,以及一个打印函数print。由于默认的访问权限是public,因此这些成员都可以在结构体外部访问。可以使用如下方式初始化Point结构体:Point

p1

=

{1,

2};

//

使用花括号初始化

Point

p2

{3,

4};

//

不使用等号初始化classclass也是一种自定义数据类型,可以包含数据成员和函数成员。它的默认访问权限是private,默认的继承方式是private,默认成员类型是private。下面是一个class的例子:class

Rectangle

{

private:

int

width;

int

height;

public:

Rectangle(int

w,

int

h)

:

width(w),

height(h)

{}

int

area()

{

return

width

*

height;

}

};上面的代码定义了一个Rectangle类,它包含了两个int类型的私有数据成员width和height,以及一个公有构造函数Rectangle和一个公有成员函数area。由于默认的访问权限是private,因此这些成员只能在类内部或者通过类的公有成员函数访问。可以使用如下方式初始化Rectangle类:Rectangle

r1(2,

3);

//

使用括号初始化

Rectangle

r2

=

Rectangle(4,

5);

//

使用等号初始化区别struct的默认访问权限是public,而class的默认访问权限是private。struct的默认继承方式是public,而class的默认继承方式是private。struct的默认成员类型是public,而class的默认成员类型是private。在使用struct时可以省略关键字struct,而在使用class时不能省略关键字class。在C++中,struct和class可以互相继承,区别仅在于默认访问权限和默认继承方式的不同。对象的内存存储模型相较于C语言,C++语言并没有额外增加内存消耗(确切说,在没有虚函数情况下)。对于一个C++类对象,每个对象有独立的数据成员(非static),但是内存中成员函数只有一份,该类的所有对象共享成员函数。static数据成员属于类,该类的所有对象共享static数据成员,static数据成员存储在静态存储区。对象数据成员依据创建对象的方式不同,可能存在于栈上或者堆上。成员函数存储在代码段。无继承状态Class

Base

{

public:

int

a;

int

b;

virtual

void

function();

};首先是虚函数表指针,该指针是由编译器定义和初始化(编译阶段,编译器在构造函数内增加代码实现)成员函数代码存储在代码段,堆上构造虚函数表,将虚成员函数的地址存储在虚函数内。数据成员按照声明的顺序布局;单继承无虚函数class

A

{

public:

int

a;

int

b;

void

fun1();

void

fun2();

};

class

B

:

public

A

{

public:

int

c;

void

fun2();

}B继承A类其中a,b的数据是共享的,数据存储与栈区fun()1,A::fun2(),B::fun2()都存在与代码区中虚函数多继承class

A

{

public:

int

a;

int

b;

virtual

void

vfun1();

virtual

void

vfun2();

void

fun1();

void

fun2();

};

class

B

:

public

class

A

{

public:

int

c;

virtual

void

vfun1();

virtual

void

vfun2();

void

fun2();

};

class

C

:

public

Class

B

{

public:

int

d;

virtual

void

vfun1();

void

fun2();

}B继承A类其中a,b的数据是共享的,数据存储与栈区fun()1,A::fun2(),B::fun2()都存在与代码区中虚函数多继承classA{public:inta;intb;virtualvoidvfun1();virtualvoidvfun2();voidfun1();voidfun2();};classB:publicclassA{public:intc;virtualvoidvfun1();virtualvoidvfun2();voidfun2();};classC:publicClassB{public:intd;virtualvoidvfun1();voidfun2();}A类中存在着整型变量a,b,普通成员函数fun1(),fun2()。虚函数vfun1(),vfun2().由于虚函数的存在那么存在着虚表指针vpter*指向A的虚函数表,A的虚函数表中存储着A::vfun1()与A::vfun2()虚函数在代码区中的地址。B继承了A的公共区内容,且B类中定义了一个整型变量c,同时对A类中的虚函数vfun1()虚函数进行重写,而虚函数vfun2()没有进行重写。所以,B类在内存的数据结构是a,b,与类A进行共享,C则属于B类自己的内容。A类无法访问。由于B重写了从A类中继承过来的虚函数vfun1(),而vfun2没有。所以B::vfun1()在代码区中是独立的地址空间,而vfun2()是共享A类的。C继承了B类的内容,所以C类中的数据a,b与A,B类共享,C的数据与B共享,d的数据属于C类自己。同理C类也没有重写A类中的vfun2()虚函数,所以在地址上vfun2()与A、B数据进行共享。vfun1()重写了所以属于自己的地址内存空间。而对于非虚函数的成员B,C类是继承A类的fun1(),fun2()的,所以他们俩是共享A::fun1(),与A::fun2()的地址空间,而B类里面的非虚函数fun2()只是与A类的fun2()名字相同,实际上是独属于B::的fun2(),所以B类里面的fun2()在代码区中有自己的地址空间B::fun2()同理对C类也是这样.C类里面fun2()是名字于A类相同而已,实际上存储的内存空间为C::fun2();创建对象classStudent{public://成员变量char*name;intage;floatscore;//成员函数voidsay(){cout<<name<<"的年龄是"<<age<<",成绩是"<<score<<endl;}};有了Student类后,就可以通过它来创建对象了,例如:StudentliLei;//创建对象在创建对象时,class关键字可要可不要,但是出于习惯我们通常会省略掉class关键字,例如:classStudentLiLei;//正确StudentLiLei;//同样正确除了创建单个对象,还可以创建对象数组StudentallStu[100];C语言中经典的指针在C++中仍然广泛使用,尤其是指向对象的指针,上面代码中创建的对象stu在栈上分配内存,需要使用&获取它的地址,例如:Studentstu;Student*pStu=&stu;当然,你也可以在堆上创建对象,这个时候就需要使用前面讲到的new关键字Student*pStu=newStudent;在栈上创建出来的对象都有一个名字,比如stu,使用指针指向它不是必须的。但是通过new创建出来的对象就不一样了,它在堆上分配内存,没有名字,只能得到一个指向它的指针,所以必须使用一个指针变量来接收这个指针,否则以后再也无法找到这个对象了,更没有办法使用它。也就是说,使用new在堆上创建出来的对象是匿名的,没法直接使用,必须要用一个指针指向它,再借助指针来访问它的成员变量或成员函数。栈内存是程序自动管理的,不能使用delete删除在栈上创建的对象;堆内存由程序员管理,对象使用完毕后可以通过delete删除。在实际开发中,new和delete往往成对出现,以保证及时删除不再使用的对象,防止无用内存堆积。对象内的值初始化在C++中,对象内的数据可以通过以下三种方式进行初始化:1,默认初始化如果一个类中的成员变量没有被显式地初始化,并且没有定义默认的构造函数,那么这个成员变量就会被默认初始化。默认初始化的规则是,基本数据类型会被初始化为0,而对象类型会被默认构造函数初始化。classMyClass{public:intnum;//num默认初始化为0std::stringstr;//str默认初始化为空字符串};intmain(){MyClassobj;std::cout<<obj.num<<std::endl;//输出0std::cout<<obj.str<<std::endl;//输出空字符串return0;}2,成员初始化列表使用成员初始化列表可以在对象创建时直接对成员变量进行初始化,而不是等到对象创建后再进行初始化。成员初始化列表在构造函数中使用冒号“:”进行声明,多个成员之间用逗号“,”隔开。classMyClass{public:intnum;std::stringstr;MyClass(intn,conststd::string&s):num(n),str(s){}//使用成员初始化列表};intmain(){MyClassobj(100,"hello");std::cout<<obj.num<<std::endl;//输出100std::cout<<obj.str<<std::endl;//输出helloreturn0;}3,赋值初始化对象的成员变量也可以通过赋值进行初始化,赋值初始化发生在对象创建后。。classMyClass{public:intnum;std::stringstr;};intmain(){MyClassobj;obj.num=100;obj.str="hello";std::cout<<obj.num<<std::endl;//输出100std::cout<<obj.str<<std::endl;//输出helloreturn0;}总结在C++中,对象内的数据可以通过默认初始化、成员初始化列表和赋值初始化进行初始化。默认初始化会根据数据类型进行默认值的初始化,成员初始化列表在对象创建时直接对成员变量进行初始化,赋值初始化发生在对象创建后。使用成员初始化列表可以提高代码的可读性和效率。对象数组在C++中,我们可以定义对象数组,也就是将同一种类型的对象存储在一个数组中。定义对象数组的语法如下:ClassNamearrayName[arraySize];其中,ClassName是对象类型,arrayName是数组的名称,arraySize是数组的大小。例如,下面定义了一个包含三个MyClass对象的对象数组classMyClass{public:intnum;MyClass(intn):num(n){}};intmain(){MyClassmyArray[3]={MyClass(1),MyClass(2),MyClass(3)};return0;}上述代码中,我们定义了一个包含三个MyClass对象的对象数组myArray。这个数组被初始化为三个MyClass对象,每个对象的num值分别为1、2、3。当我们定义对象数组时,每个对象都会被自动调用它们的构造函数进行初始化。因此,我们必须确保该类型有可用的构造函数。访问对象数组的元素与访问一般的数组元素一样,可以使用下标运算符“[]”来访问。MyClassmyArray[3]={MyClass(1),MyClass(2),MyClass(3)};std::cout<<myArray[0].num<<std::endl;//输出1std::cout<<myArray[1].num<<std::endl;//输出2std::cout<<myArray[2].num<<std::endl;//输出3总结在C++中,我们可以定义对象数组来存储同一类型的对象。定义对象数组的语法为ClassNamearrayName[arraySize]。每个对象都会被自动调用它们的构造函数进行初始化。我们可以使用下标运算符“[]”来访问对象数组的元素。C++成员对象和封闭类在C++中,成员对象是一个类的成员变量,这个成员变量是另一个类的对象。这种情况下,我们通常把包含成员对象的类称为封闭类,被包含的成员对象称为嵌套类或成员子对象。例如,下面定义了一个封闭类Person,包含一个成员对象Birthday:classBirthday{public:intyear;intmonth;intday;Birthday(inty,intm,intd):year(y),month(m),day(d){}};classPerson{public:std::stringname;Birthdaybirthday;//Birthday作为成员对象Person(conststd::string&n,constBirthday&b):name(n),birthday(b){}};intmain(){Birthdayb(1990,10,1);Personp("Tom",b);std::cout<<<<"'sbirthdayis"<<p.birthday.year<<"-"<<p.birthday.month<<"-"<<p.birthday.day<<std::endl;return0;}上述代码中,我们定义了一个Birthday类和一个Person类,其中Person类包含一个Birthday对象作为成员对象。在main函数中,我们创建了一个Birthday对象b和一个Person对象p,将b作为参数传递给p的构造函数。在输出语句中,我们访问了p对象的name成员变量和birthday成员对象的year、month和day成员变量。需要注意的是,成员对象的初始化顺序是在封闭类构造函数的初始化列表中按照声明顺序初始化的。例如,如果我们在Person类中将birthday成员对象定义在name成员变量之前,那么在Person的构造函数中,初始化列表中也应该将birthday放在name前面。classPerson{public:Birthdaybirthday;std::stringname;Person(constBirthday&b,conststd::string&n):birthday(b),name(n){}};总结在C++中,成员对象是一个类的成员变量,这个成员变量是另一个类的对象。封闭类包含成员对象,被包含的成员对象称为嵌套类或成员子对象。成员对象的初始化顺序是在封闭类构造函数的初始化列表中按照声明顺序初始化的。this指针在C++中,每个对象都有一个指向自己的指针,这个指针称为this指针。this指针可以让我们在类的成员函数中访问调用该函数的对象的成员变量和成员函数。this指针是一个隐式参数,它被自动传递给成员函数。在类的成员函数中,可以使用this指针来访问对象的成员变量和成员函数。例如:classPerson{public:std::stringname;intage;voidsetName(conststd::string&n){this->name=n;//使用this指针访问name成员变量}voidsetAge(inta){age=a;//直接访问age成员变量}voidprintInfo(){std::cout<<"Name:"<<this->name<<",Age:"<<this->age<<std::endl;//使用this指针访问成员变量}};intmain(){Personp;p.setName("Tom");p.setAge(20);p.printInfo();return0;}上述代码中,我们定义了一个Person类,其中包含两个成员变量name和age,以及三个成员函数setName、setAge和printInfo。在setName和printInfo函数中,我们使用了this指针来访问对象的成员变量name和age。在setAge函数中,我们直接访问了age成员变量。在main函数中,我们创建了一个Person对象p,并分别调用了它的setName、setAge和printInfo函数来设置和输出对象的成员变量值。需要注意的是,this指针在成员函数中是一个局部变量,它指向调用该函数的对象,因此每个对象都有自己的this指针。在成员函数中,我们可以使用this指针来访问调用该函数的对象的成员变量和成员函数。如果一个成员函数没有使用this指针访问任何成员变量或成员函数,那么this指针将不会被使用,编译器不会为该函数生成this指针。this只能用在类的内部,通过this可以访问类的所有成员,包括private、protected、public属性的。总结在C++中,每个对象都有一个指向自己的指针,这个指针称为this指针。this指针可以让我们在类的成员函数中访问调用该函数的对象的成员变量和成员函数。在成员函数中,我们可以使用this指针来访问调用该函数的对象的成员变量和成员函数。如果一个成员函数没有使用this指针访问任何成员变量或成员函数,那么this指针将不会被使用,编译器不会为该函数生成this指针。C++静态成员变量对象的内存中包含了成员变量,不同的对象占用不同的内存使得不同对象的成员变量相互独立,它们的值不受其他对象的影响。例如有两个相同类型的对象a、b,它们都有一个成员变量m_name,那么修改a.m_name的值不会影响b.m_name的值。有时候我们希望在多个对象之间共享数据,对象a改变了某份数据后对象b可以检测到。共享数据的典型使用场景是计数,以前面的Student类为例,如果我们想知道班级中共有多少名学生,就可以设置一份共享的变量,每次创建对象时让该变量加1。classStudent{public:Student(char*name,intage,floatscore);voidshow();public:staticintm_total;//静态成员变量private:char*m_name;intm_age;floatm_score;}static成员变量属于类,不属于某个具体的对象,即使创建多个对象,也只为m_total分配一份内存,所有对象使用的都是这份内存中的数据。当某个对象修改了m_total,也会影响到其他对象。static成员变量的内存既不是在声明类时分配,也不是在创建对象时分配,而是在(类外)初始化时分配。反过来说,没有在类外初始化的static成员变量不能使用。//通过类类访问static成员变量Student::m_total=10;//通过对象来访问static成员变量Studentstu("小明",15,92.5f);stu.m_total=20;//通过对象指针来访问static成员变量Student*pstu=newStudent("李华",16,96);pstu->m_total=20;C++静态成员函数在类中,static除了可以声明静态成员变量,还可以声明静态成员函数。普通成员函数可以访问所有成员(包括成员变量和成员函数),静态成员函数只能访问静态成员。静态成员函数与普通成员函数的根本区别在于:普通成员函数有this指针,可以访问类中的任意成员;而静态成员函数没有this指针,只能访问静态成员(包括静态成员变量和静态成员函数)。#include<iostream>usingnamespacestd;classStudent{public:Student(char*name,intage,floatscore);voidshow();public://声明静态成员函数staticintgetTotal();staticfloatgetPoints();private:staticintm_total;//总人数staticfloatm_points;//总成绩private:char*m_name;intm_age;floatm_score;};intStudent::m_total=0;floatStudent::m_points=0.0;Student::Student(char*name,intage,floatscore):m_name(name),m_age(age),m_score(score){m_total++;m_points+=score;}voidStudent::show(){cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;}//定义静态成员函数intStudent::getTotal(){returnm_total;}floatStudent::getPoints(){returnm_points;}intmain(){(newStudent("小明",15,90.6))->show();(newStudent("李磊",16,80.5))->show();(newStudent("张华",16,99.0))->show();(newStudent("王康",14,60.8))->show();inttotal=Student::getTotal();floatpoints=Student::getPoints();cout<<"当前共有"<<total<<"名学生,总成绩是"<<points<<",平均分是"<<points/total<<endl;return0;}小明的年龄是15,成绩是90.6李磊的年龄是16,成绩是80.5张华的年龄是16,成绩是99王康的年龄是14,成绩是60.8当前共有4名学生,总成绩是330.9,平均分是82.725C++const成员变量和成员函数const成员变量的用法和普通const变量的用法相似,只需要在声明时加上const关键字。初始化const成员变量只有一种方法,就是通过构造函数的初始化列表classStudent{public:Student(char*name,intage,floatscore);voidshow();//声明常成员函数char*getname()const;intgetage()const;floatgetscore()const;private:char*m_name;intm_age;floatm_score;};Student::Student(char*name,intage,floatscore):m_name(name),m_age(age),m_score(score){}voidStudent::show(){cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;}//定义常成员函数char*Student::getname()const{returnm_name;}intStudent::getage()const{returnm_age;}floatStudent::getscore()const{returnm_score;}const成员函数可以使用类中的所有成员变量,但是不能修改它们的值,这种措施主要还是为了保护数据而设置的。const成员函数也称为常成员函数。注意事项需要强调的是,必须在成员函数的声明和定义处同时加上const关键字。char*getname()const和char*getname()是两个不同的函数原型,如果只在一个地方加const会导致声明和定义处的函数原型冲突。函数开头的const用来修饰函数的返回值,表示返回值是const类型,也就是不能被修改,例如constchar*getname()函数头部的结尾加上const表示常成员函数,这种函数只能读取成员变量的值,而不能修改成员变量的值,例如char*getname()constC++const对象在C++中,const也可以用来修饰对象,称为常对象。一旦将对象定义为常对象之后,就只能调用类的const成员(包括const成员变量和const成员函数)了#include<iostream>usingnamespacestd;classStudent{public:Student(char*name,intage,floatscore);public:voidshow();char*getname()const;intgetage()const;floatgetscore()const;private:char*m_name;intm_age;floatm_score;};Student::Student(char*name,intage,floatscore):m_name(name),m_age(age),m_score(score){}voidStudent::show(){cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;}char*Student::getname()const{returnm_name;}intStudent::getage()const{returnm_age;}floatStudent::getscore()const{returnm_score;}intmain(){constStudentstu("小明",15,90.6);//stu.show();//errorcout<<stu.getname()<<"的年龄是"<<stu.getage()<<",成绩是"<<stu.getscore()<<endl;constStudent*pstu=newStudent("李磊",16,80.5);//pstu->show();//errorcout<<pstu->getname()<<"的年龄是"<<pstu->getage()<<",成绩是"<<pstu->getscore()<<endl;return0;}C++友元函数和友元类在C++中,一个类中可以有public、protected、private三种属性的成员,通过对象可以访问public成员,只有本类中的函数可以访问本类的private成员。现在,我们来介绍一种例外情况——友元(friend)。借助友元(friend),可以使得其他类中的成员函数以及全局范围内的函数访问当前类的private成员。1,友元函数在单继承中,友元函数的使用方式与普通类中的使用方式相同。可以在类中声明一个函数为友元函数,使得该函数可以访问该类的私有成员变量和成员函数。classA{private:intx;public:friendvoidfoo(A&a);};voidfoo(A&a){a.x=10;//可以访问A类的私有成员变量x}intmain(){Aa;foo(a);return0;}在上面的代码中,我们声明了一个类A,并在其中声明了一个函数foo为友元函数。在foo中,我们可以直接访问A类的私有成员变量x,并将其赋值为10。在主函数中,我们创建了一个A类的实例a,并将其作为参数传递给foo函数,从而实现了对A类的私有成员变量x的修改。2,友元类友元类的使用方式与普通类中的使用方式相同。可以在类中声明另外一个类为友元类,使得该类可以访问该类的私有成员变量和成员函数。下面是一个示例:classA{private:intx;public:friendclassB;};classB{public:voidfoo(A&a){a.x=10;//可以访问A类的私有成员变量x}};intmain(){Aa;Bb;b.foo(a);//调用B类的成员函数foo,修改A类的私有成员变量xreturn0;}在上面的代码中,我们声明了一个类A,并在其中声明了一个类B为友元类。在类B中,我们声明了一个成员函数foo,并在其中访问了A类的私有成员变量x,并将其赋值为10。在主函数中,我们创建了一个A类的实例a和一个B类的实例b,并将a作为参数传递给b的成员函数foo,从而实现了对A类的私有成员变量x的修改。注意事项需要注意的是,如果一个类A是另外一个类B的友元类,那么在B中可以访问A的私有成员变量和成员函数,但是在A中不能访问B的私有成员变量和成员函数。这是由于友元关系是单向的。如果需要在A中访问B的私有成员变量和成员函数,需要在B中再次声明A为友元类。作用域C++的作用域是指变量、函数、类等标识符在程序中可以被访问的范围。在C++中,作用域分为以下四种:全局作用域:全局作用域是指在程序的任何地方都可以访问的标识符。在C++中,全局作用域包括全局变量、全局函数和命名空间中的标识符。类作用域:类作用域是指在类的成员函数中可以访问的标识符。在C++中,类作用域包括类的成员变量、成员函数和友元函数。块作用域:块作用域是指在一个代码块(花括号{}之间的代码)中定义的标识符。在C++中,块作用域包括局部变量、函数参数和代码块中的标识符。命名空间作用域:命名空间作用域是指在命名空间中定义的标识符。在C++中,命名空间作用域包括命名空间中的变量、函数和类。下面通过代码是全局作用域#include<iostream>usingnamespacestd;intglobal_var=10;//全局变量namespaceA{intnamespace_var=20;//命名空间变量classTest{public:voidfunc(){intclass_var=30;//类的成员变量cout<<"class_var:"<<class_var<<endl;cout<<"namespace_var:"<<namespace_var<<endl;cout<<"global_var:"<<global_var<<endl;}};}intmain(){intlocal_var=40;//局部变量A::Testt;t.func();cout<<"local_var:"<<local_var<<endl;cout<<"namespace_var:"<<A::namespace_var<<endl;cout<<"global_var:"<<global_var<<endl;return0;}在上面的代码中,我们定义了一个全局变量global_var,一个命名空间A,一个命名空间变量namespace_var和一个类Test,在类中定义了一个成员变量class_var和一个成员函数func,在main函数中定义了一个局部变量local_var。在Test类的成员函数func中,可以访问类的成员变量class_var、命名空间变量namespace_var和全局变量global_var。在main函数中,可以访问局部变量local_var、命名空间变量namespace_var和全局变量global_var。类作用域中的类成员作用域classPerson{public:voidsetName(std::stringname){this->name=name;}std::stringgetName(){returnname;}private:std::stringname;};intmain(){Personperson;person.setName("Alice");std::cout<<person.getName()<<std::endl;return0;}类作用域classPerson{public:classAddress{public:Address(std::stringcountry,std::stringcity):country(country),city(city){}std::stringgetCountry(){returncountry;}std::stringgetCity(){returncity;}private:std::stringcountry;std::stringcity;};voidsetAddress(Addressaddress){this->address=address;}AddressgetAddress(){returnaddress;}private:Addressaddress;};intmain(){Person::Addressaddress("China","Beijing");Personperson;person.setAddress(address);std::cout<<person.getAddress().getCountry()<<","<<person.getAddress().getCity()<<std::endl;return0;}在上面的例子中,类Person定义了一个类类型Address,可以在类外部使用“Person::Address”来访问这个类类型。块作用域C++的块作用域是指在一对花括号内定义的变量或对象只在这个花括号内有效,出了这个花括号就失效了。这种特性可以用来控制变量的可见性和生命周期。#include<iostream>intmain(){intx=1;{inty=2;std::cout<<"x+y="<<x+y<<std::endl;//输出x+y=3}std::cout<<"x+y="<<x+y<<std::endl;//编译错误,y不在作用域内return0;}在上面的代码中,变量x是在main函数的作用域中定义的,它的作用域是整个main函数。而变量y是在{}内部定义的,它的作用域只在这个花括号内部。所以在第一个cout语句中,x和y都是有效的,可以正常计算。但在第二个cout语句中,y已经超出了作用域,所以编译器会报错。需要注意的是,如果在内部作用域中定义了与外部作用域中同名的变量,那么内部作用域中的变量会覆盖外部作用域中的变量,直到内部作用域结束为止。例如:#include<iostream>intmain(){intx=1;{intx=2;std::cout<<"x="<<x<<std::endl;//输出x=2}std::cout<<"x="<<x<<std::endl;//输出x=1return0;}在上面的代码中,内部作用域中定义了一个名为x的变量,它会覆盖外部作用域中的x变量。所以第一个cout语句输出的是内部作用域中的x变量,而第二个cout语句输出的是外部作用域中的x变量。命名空间作用域命名空间的作用域是指命名空间中定义的标识符(如函数、变量、类等)在程序中的可见范围。命名空间的作用域可以分为两种1,未限定作用域未限定作用域是指在命名空间外部直接使用命名空间中定义的标识符namespacemy_namespace{intmy_var=1;}intmain(){std::cout<<my_namespace::my_var<<std::endl;//输出1return0;}在未限定作用域中,必须使用命名空间限定符(如my_namespace::)来访问命名空间中的标识符。2.限定作用域限定作用域是指在命名空间内部或使用了命名空间限定符的作用域中使用命名空间中定义的标识符。例如:namespacemy_namespace{intmy_var=1;voidmy_func(){intmy_var=2;std::cout<<my_var<<std::endl;//输出2std::cout<<my_namespace::my_var<<std::endl;//输出1}}intmain(){my_namespace::my_func();return0;}在限定作用域中,可以直接使用命名空间中定义的标识符,也可以使用命名空间限定符来访问其他命名空间中的标识符。需要注意的是,命名空间的作用域也受到同名标识符的影响。如果在命名空间中定义了与全局作用域或其他命名空间中的标识符同名的标识符,因此需要做出限制。如下namespacemy_namespace{intmy_var=1;}intmy_var=2;intmain(){std::cout<<my_var<<std::endl;//输出2std::cout<<my_namespace::my_var<<std::endl;//输出1return0;}命名空间可以嵌套namespaceA{inta=1000;namespaceB{inta=2000;}}voidtest03(){cout<<"A中的a="<<A::a<<endl;//1000cout<<"B中的a="<<A::B::a<<endl;//2000}命名空间是开放的,即可以随时把新的成员加入已有的命名空间中(常用)namespaceA{inta=100;intb=200;}//将c添加到已有的命名空间A中namespaceA{intc=300;}voidtest04(){cout<<"A中a="<<A::a<<endl;//100cout<<"A中c="<<A::c<<endl;//200}命名空间中的函数可以在“命名空间”外定义namespaceA{inta=100;//变量voidfunc();}voidA::func()//成员函数在外部定义的时候记得加作用域{//访问命名空间的数据不用加作用域cout<<"func遍历a="<<a<<endl;}voidfunb()//普通函数{cout<<"funb遍历a="<<A::a<<endl;}voidtest06(){A::func();funb();}无名命名空间,意味着命名空间中的标识符只能在本文件内访问,相当于给这个标识符加上了static,使得其可以作为内部连接namespace{inta=10;voidfunc(){cout<<"hellonamespace"<<endl;}}voidtest(){//只能在当前源文件直接访问a或funccout<<"a="<<a<<endl;func();}命名空间可取别名namespaceveryLongName{inta=10;voidfunc(){cout<<"hellonamespace"<<endl;}}voidtest(){namespaceshortName=veryLongName;cout<<"ve

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论