C++学习
类
一、定义
class 类名
{public: //外界可以直接访问或者调用private: //不能被外部所访问或调用, 只能被本类内部访问
};
二、类的成员函数
-
类的成员函数是指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样。类成员函数是类的一个成员,它可以操作类的任意对象,可以访问对象中的所有成员。
-
成员函数可以定义在类定义内部,或者单独使用范围解析运算符 :: 来定义。
class Box
{public:double length; // 长度double breadth; // 宽度double height; // 高度double getVolume(void){return length * breadth * height;}
};
或是:
double Box::getVolume(void)
{return length * breadth * height;
}
三、访问修饰符
class Base {public:// 公有成员protected:// 受保护成员private:// 私有成员};
- public 公有成员
在程序中类的外部是可访问的,可以不使用任何成员函数来设置和获取公有变量的值。
- protected 受保护成员
protected(受保护)成员在派生类(即子类)中是可访问的。
在这里 width 成员可被派生类 smallBox 的任何成员函数访问。
#include <iostream>
using namespace std;class Box
{protected:double width;
};class SmallBox:Box // SmallBox 是派生类
{public:void setSmallWidth( double wid );double getSmallWidth( void );
};// 子类的成员函数
double SmallBox::getSmallWidth(void)
{return width ;
}void SmallBox::setSmallWidth( double wid )
{width = wid;
}// 程序的主函数
int main( )
{SmallBox box;// 使用成员函数设置宽度box.setSmallWidth(5.0);cout << "Width of box : "<< box.getSmallWidth() << endl;return 0;
}
- private 私有成员
私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员。
默认情况下,类的所有成员都是私有的。
实际操作中,我们一般会在私有区域定义数据,在公有区域定义相关的函数,以便在类的外部也可以调用这些函数,如下所示:
#include <iostream>using namespace std;class Box
{public:double length;void setWidth( double wid );double getWidth( void );private:double width;
};// 成员函数定义
double Box::getWidth(void)
{return width ;
}void Box::setWidth( double wid )
{width = wid;
}// 程序的主函数
int main( )
{Box box;// 不使用成员函数设置长度box.length = 10.0; // OK: 因为 length 是公有的cout << "Length of box : " << box.length <<endl;// 不使用成员函数设置宽度// box.width = 10.0; // Error: 因为 width 是私有的box.setWidth(10.0); // 使用成员函数设置宽度cout << "Width of box : " << box.getWidth() <<endl;return 0;
}
输出
Length of box : 10
Width of box : 10
继承中的修饰符:
有public, protected, private三种继承方式,它们相应地改变了基类成员的访问属性。
1.public 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:public, protected, private
2.protected 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:protected, protected, private
3.private 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:private, private, private
但无论哪种继承方式,上面两点都没有改变:
1.private 成员只能被本类成员(类内)和友元访问,不能被派生类访问;
2.protected 成员可以被派生类访问。
四、类的构造函数 ~
类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。
构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。
#include <iostream>using namespace std;class Line
{public:void setLength( double len );double getLength( void );Line(); // 这是构造函数private:double length;
};// 成员函数定义,包括构造函数
Line::Line(void)
{cout << "Object is being created" << endl;
}void Line::setLength( double len )
{length = len;
}double Line::getLength( void )
{return length;
}
// 程序的主函数
int main( )
{Line line;// 设置长度line.setLength(6.0); cout << "Length of line : " << line.getLength() <<endl;return 0;
}
Object is being created
Length of line : 6
默认的构造函数没有任何参数,但如果需要,构造函数也可以带有参数。这样在创建对象时就会给对象赋初始值。
构造函数可分为:无参构造函数、有参构造函数、拷贝构造函数(参数为const ClassName &vriable 这个比较复杂)。
默认是无参数构造函数, 当你想在构造的时候传参数进去, 那么自己就要写个有参数的构造函数;
例如:
class A1{ //使用默认构造函数,无参数
}
class A2{
A2(int c){ m_c=c } //有参数构造函数, 可以传达一个值初始化成员变量
int m_c;
}
调用:
A1 a1; //默认构造函数, 无参数
A2 a2(10); //有参数构造函数, 传达参数10,初始化成员变量 a2.m_c;
C++默认提供拷贝构造函数是指向的浅拷贝。只是进行了简单的成员变量的值的复制。
五、类的析构函数
- 类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。
- 析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
#include <iostream>using namespace std;class Line
{public:void setLength( double len );double getLength( void );Line(); // 这是构造函数声明~Line(); // 这是析构函数声明private:double length;
};// 成员函数定义,包括构造函数
Line::Line(void)
{cout << "Object is being created" << endl;
}
Line::~Line(void)
{cout << "Object is being deleted" << endl;
}void Line::setLength( double len )
{length = len;
}double Line::getLength( void )
{return length;
}
// 程序的主函数
int main( )
{Line line;// 设置长度line.setLength(6.0); cout << "Length of line : " << line.getLength() <<endl;return 0;
}
Object is being created
Length of line : 6
Object is being deleted
六、拷贝构造函数
拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:
-
通过使用另一个同类型的对象来初始化新创建的对象。
-
复制对象把它作为参数传递给函数。
-
复制对象,并从函数返回这个对象。
-
如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。拷贝构造函数的最常见形式如下:
classname (const classname &obj) {// 构造函数的主体
}
七、友元函数
类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。
友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。
如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend,如下所示:
#include <iostream>using namespace std;class Box
{double width;
public:friend void printWidth( Box box ); //友元函数void setWidth( double wid );
};// 成员函数定义
void Box::setWidth( double wid )
{width = wid;
}// 请注意:printWidth() 不是任何类的成员函数
void printWidth( Box box )
{/* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */cout << "Width of box : " << box.width <<endl;
}// 程序的主函数
int main( )
{Box box;// 使用成员函数设置宽度box.setWidth(10.0);// 使用友元函数输出宽度printWidth( box );return 0;
}
八、内联函数
C++ 内联函数是通常与类一起使用。如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。
如果想把一个函数定义为内联函数,则需要在函数名前面放置关键字 inline,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略 inline 限定符。
在类定义中的定义的函数都是内联函数,即使没有使用 inline 说明符。
九、this 指针
在 C++ 中,每一个对象都能通过 this 指针来访问自己的地址。this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。
- 友元函数没有 this 指针,因为友元不是类的成员。只有成员函数才有 this 指针。
- this指针在成员函数的开始执行前构造的,在成员的执行结束后清除。
- this指针不能再静态函数中使用
#include <iostream>using namespace std;class Box
{public:// 构造函数定义Box(double l=2.0, double b=2.0, double h=2.0){cout <<"Constructor called." << endl;length = l;breadth = b;height = h;}double Volume(){return length * breadth * height;}int compare(Box box){return this->Volume() > box.Volume(); //this指针}private:double length; // Length of a boxdouble breadth; // Breadth of a boxdouble height; // Height of a box
};int main(void)
{Box Box1(3.3, 1.2, 1.5); // Declare box1Box Box2(8.5, 6.0, 2.0); // Declare box2if(Box1.compare(Box2)){cout << "Box2 is smaller than Box1" <<endl;}else{cout << "Box2 is equal to or larger than Box1" <<endl;}return 0;
}
C++指针
C语言指针
十、指向类的指针
一个指向类的指针与指向结构的指针类似,访问指向类的的指针的成员,需要使用成员访问运算符—>,就像访问指向结构的指针一样,与所有的指针一样,在使用前必须对指针初始化。
十一、静态变量和静态方法
== 想 ==
1、静态对象
1)使用static关键字把类成员声明为静态时,后续无论创建多少个类对象,静态成员都只有一个副本;
2)静态成员在类的所有对象中都是共享的,如果不存在其他初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零,
我们不能把静态成员的初始化放置在类的定义中,但是可以在类的外部使用范围解析运算符::来重新声明静态变量从而对它进行初始化;
3)静态成员变量在类中仅仅是声明,没有定义,所以要在类的外面定义,实际上是给静态成员变量分配内存,如果不加定义就会报错,初始化是一个赋初始值,而定义是分配内存。
2、静态方法
1)如果把函数成员声明为静态的,就可以把函数与类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数 只能使用类名 范围解析运算符:: 就可以访问。
2)静态成员函数只能访问静态成员数据,其他静态成员函数和类外部的其他函数。
3)静态成员函数只有一个类范围,他不能访问this指针,可以使用静态成员函数来判断类的某些对象是否已被创建。
4)静态成员函数与普通成员函数的区别:静态成员函数没有this指针,只能访问静态成员(包括静态成员变量和静态成员函数);普通成员函数有this指针,可以访问类中的任意成员,而静态成员函数没有this指针。
#include <iostream>
#include <string>class Pet
{
public:Pet(std::string theName);~Pet();static int getCount(); //静态方法只有Pet类,外部对象调用时的接口protected:std::string name;
private: //只有类里边的方法才能访问static int count; //静态属性只有Pet类
};class Dog : public Pet //Dog来继承Pet的类
{
public :Dog(std::string theName);
};class Cat : public Pet //Cat来继承Pet的类
{
public:Cat(std::string theName);
};int Pet::count = 0; //定义分配内存,初始化赋初始值 1.编译器为count分配内存;2.把count这个变量初始化为0;Pet::Pet(std::string theName) //Pet的构造函数
{name = theName ;count++;std::cout<<"一只宠物出生了,它的名字叫:"<<name<<"\n";
};Pet::~Pet() // Pet的析构函数
{count--;std::cout<<name<<"挂掉了\n";
}int Pet::getCount()//getCount这个接口函数的作用就把count输出来
{return count;
}Dog::Dog(std::string theName) : Pet(theName)
{
}Cat::Cat(std::string theName) : Pet(theName)
{
}int main()
{Dog dog("Tom");Cat cat("Jerry");std::cout<<"\n已经诞生了"<<Pet::getCount()<<"只宠物!\n\n"; //访问方法{ //大括号的作用Dog dog_2("Tom_2");Cat cat_2("Jerry_2");std::cout<<"\n现在呢,已经诞生了"<<Pet::getCount()<<"只宠物!\n\n";}std::cout<<"\n现在还剩下"<<Pet::getCount()<<"只宠物!\n\n";getchar();return 0;
}
运行结果如下图所示:
静态成员在类的所有对象中是共享的。如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零。我们不能把静态成员的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它进行初始化,如下面的实例所示。
#include <iostream>using namespace std;class Box
{public:static int objectCount;// 构造函数定义Box(double l=2.0, double b=2.0, double h=2.0){cout <<"Constructor called." << endl;length = l;breadth = b;height = h;// 每次创建对象时增加 1objectCount++;}double Volume(){return length * breadth * height;}private:double length; // 长度double breadth; // 宽度double height; // 高度
};// 初始化类 Box 的静态成员
int Box::objectCount = 0;int main(void)
{Box Box1(3.3, 1.2, 1.5); // 声明 box1Box Box2(8.5, 6.0, 2.0); // 声明 box2// 输出对象的总数cout << "Total objects: " << Box::objectCount << endl;return 0;
}
Constructor called.
Constructor called.
Total objects: 2
静态成员函数:
如果把函数成员声明为静态的,就可以把函数与类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。
静态成员函数只能访问静态成员数据、其他静态成员函数和类外部的其他函数。
静态成员函数有一个类范围,他们不能访问类的 this 指针。您可以使用静态成员函数来判断类的某些对象是否已被创建。