参考:http://c.biancheng.net/cpp/biancheng/view/2971.html
参考:https://ruochen.blog.csdn.net/article/details/90719951?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control
1. 构造函数怎么写
首先,当类被实例化后,会自动调用构造函数,由构造函数完成对象的初始化工作,构造函数的作用:初始化对象的数据成员;
因此,构造函数中的内容:初始化对象成员(包括public、private);
class Student{
private:
char *m_name;
int m_age;
float m_score;
public:
//声明构造函数
Student(char *name, int age, float score);
//声明普通成员函数
void show();
};
//定义构造函数
Student::Student(char *name, int age, float score){
m_name = name;
m_age = age;
m_score = score;
}
//采用参数初始化表,成员变量的赋值顺序由它们在类中的声明顺序决定,初始化 const 成员变量的唯一方法就是使用参数初始化表。
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){
//TODO:
}
在栈上创建对象时,实参位于对象名后面,例如
Student stu("小明", 15, 92.5f)
;在堆上创建对象时,实参位于类名后面,例如
new Student("李华", 16, 96),
调用没有参数的构造函数也可以省略括号。
构造函数必须是 public 属性的,否则创建对象时无法调用。
- 不管是声明还是定义,函数名前面都不能出现返回值类型,即使是 void 也不允许;
- 函数体中不能有 return 语句。
构造函数是允许重载的。一个类可以有多个重载的构造函数,创建对象时根据传递的实参来判断调用哪一个构造函数。
2. 命名空间怎么写
为了解决合作开发时的命名冲突问题,C++ 引入了命名空间(Namespace)
namespace name{
//variables, functions, classes
}
使用变量、函数时要指明它们所在的命名空间。
Li :: fp = fopen("one.txt", "r"); //使用小李定义的变量 fp
Han :: fp = fopen("two.txt", "rb+"); //使用小韩定义的变量 fp
不建议全局使用 using namepace ×,可能会引起问题:增加了命名冲突的风险,但是可以局部使用,例如:在 main() 函数中声明命名空间 std,它的作用范围就位于 main() 函数内部,如果在其他函数中又用到了 std,就需要重新声明
#include <iostream>
void func(){
//必须重新声明
using namespace std;
cout<<"http://c.biancheng.net"<<endl;
}
int main(){
//声明命名空间std
using namespace std;
cout<<"C语言中文网"<<endl;
func();
return 0;
}
不同的.h中可以使用相同名字的namespace吗? 可以,会自动合并为一个名字空间,可以理解为追加
3. 常用的头文件
- #include<iostream> 使用输入输出时
- #include <string> //字符串类
4. 内存分配
在C语言中,动态分配内存用 malloc() 函数,释放内存用 free() 函数;C++中使用new 和 delete:new 用来动态分配内存,delete 用来释放内存。
int *p = new int; //分配1个int型的内存空间
delete p; //释放内存
int *p = new int[10]; //分配10个int型的内存空间
delete[] p;
通常 new 和 delete、new[] 和 delete[] 操作符应该成对出现
5. 为什么会有内联函数?
函数调用是有时间和空间开销的。如果函数体代码比较多,需要较长的执行时间,那么函数调用机制占用的时间可以忽略;如果函数只有一两条语句,那么大部分的时间都会花费在函数调用机制上,这种时间开销就就不容忽视。
指定内联函数的方法很简单,只需要在函数定义处增加 inline 关键字。一般只将那些短小的、频繁调用的函数声明为内联函数。在类体中定义的成员函数会自动成为内联函数,在类体外定义的不会。
- //内联函数,交换两个数的值
- inline void swap(int *a, int *b){
- int temp;
- temp = *a;
- *a = *b;
- *b = temp;
- }
6. 创建类和对象
c++一般在 .h文件中创建类,因为类只是一个模板(Template),编译后不占用内存空间,所以在定义类时不能对成员变量进行初始化,因为没有地方存储数据。只有在创建对象以后才会给成员变量分配内存,这个时候就可以赋值了。
通常将类的声明放在头文件中,而将成员函数的定义放在源文件中。
两种创建对象的方式:一种是在栈上创建,
Student stu;
Student *pStu = &stu;
另外一种是在堆上创建,
Student *pStu = new Student;
delete pStu; //删除对象
栈内存是程序自动管理的,不能使用 delete 删除在栈上创建的对象;堆内存由程序员管理,对象使用完毕后可以通过 delete 删除。
7. 访问权限
在类的内部(定义类的代码内部,定义类的.h和.cpp),无论成员被声明为 public、protected 还是 private,都是可以互相访问的,没有访问权限的限制。
在类的外部(定义类的代码之外),只能通过对象访问成员,并且通过对象只能访问 public 属性的成员,不能访问 private、protected 属性的成员。
成员变量大都以
m_
开头,这是约定成俗的写法,不是语法规定的内容。以
m_
开头既可以一眼看出这是成员变量,又可以和成员函数中的形参名字区分开。
//类的声明
class Student{
private: //私有的
char *m_name;
int m_age;
float m_score;
public: //共有的
void setname(char *name);
void setage(int age);
void setscore(float score);
void show();
};
根据C++软件设计规范,实际项目开发中的成员变量以及只在类内部使用的成员函数(只被成员函数调用的成员函数)都建议声明为 private,而只将允许通过对象调用的成员函数声明为 public。
给成员变量赋值的函数通常称为 set 函数,它们的名字通常以
set
开头,后跟成员变量的名字;读取成员变量的值的函数通常称为 get 函数,它们的名字通常以
get
开头,后跟成员变量的名字。
除了 set 函数和 get 函数,在创建对象时还可以调用构造函数来初始化各个成员变量
8. 析构函数
析构函数没有参数,不能被重载,因此一个类只能有一个析构函数。
在所有函数之外创建的对象是全局对象,它和全局变量类似,位于内存分区中的全局数据区,程序在结束执行时会调用这些对象的析构函数。
在函数内部创建的对象是局部对象,它和局部变量类似,位于栈区,在局部函数执行结束时会调用这些对象的析构函数。
new 创建的对象位于堆区,通过 delete 删除时才会调用析构函数;如果没有 delete,析构函数就不会被执行。
9. this指针
this 是 const 指针,this 只能在成员函数内部使用,用在其他地方没有意义,也是非法的
10. 静态成员变量和静态成员函数
使用静态成员变量来实现多个对象共享数据的目标,就相当于类中的全局变量;
static 成员变量必须在类声明的外部初始化,具体形式为:
type class::name = value;
static 成员变量既可以通过对象来访问,也可以通过类来访问
静态成员函数只能访问静态成员,静态成员函数与普通成员函数的根本区别在于:普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。
11. const关键字
const 可以用来修饰成员变量、成员函数以及对象。如果你不希望某些数据被修改,可以使用
const
关键字加以限定。
const 成员函数可以使用类中的所有成员变量,但是不能修改它们的值;常成员函数需要在声明和定义的时候在函数头部的结尾加上 const 关键字
class Student{
public:
Student(char *name, int age, float score);
void show();
//声明常成员函数
char *getname() const;
int getage() const;
float getscore() const;
private:
char *m_name;
int m_age;
float m_score;
};
//定义常成员函数
char * Student::getname() const{
return m_name;
}
12. friend友元函数和友元类
在当前类以外定义的、不属于当前类的函数也可以在类中声明,但要在前面加 friend 关键字,这样就构成了友元函数。
友元函数不同于类的成员函数,在友元函数中不能直接访问类的成员,必须要借助对象。
class Student{
public:
Student(char *name, int age, float score);
public:
friend void show(Student *pstu); //将show()声明为友元函数
private:
char *m_name;
int m_age;
float m_score;
};
//非成员函数
void show(Student *pstu){
cout<<pstu->m_name<<"的年龄是 "<<pstu->m_age<<",成绩是 "<<pstu->m_score<<endl;
}