您现在的位置是:首页 >学无止境 >C++面向对象(黑马程序员)网站首页学无止境
C++面向对象(黑马程序员)
简介C++面向对象(黑马程序员)
内存分区模型
#include<iostream>
using namespace std;
//栈区数据注意事项:不要返回局部变量的地址
//栈区的数据由编译器管理开辟和释放
int* func(int b) //形参数据也会放在栈区
{
b = 100;
int a = 10; //局部变量存放在栈区,栈区的数据在函数执行完后自动释放
return &a; //返回局部变量的地址
}
int main()
{
int * p = func(1); //接受func()函数的返回值
cout << *p << endl; //第一次可以打印正确的数字,是因为编译器做了保留
cout << *p << endl; //第二次这个数据就不再保留了
system("pause");
return 0;
}
new操作
#include<iostream>
using namespace std;
int* func()
{
//在堆区创建一个整形数据
//new返回是该数据类型的指针
int* p = new int(10);
return p;
}
void test01()
{
int* p = func();
cout << *p << endl;
//堆区数据由程序员管理释放
//释放使用delete
delete p;
cout << *p << endl; //内存已释放,再次访问属于非法操作
}
void test02()
{
//创建10个征信数据的数组在堆区
int* arr = new int[10];
for (int i = 0; i < 10; i++)
{
arr[i] = i + 100;
}
for (int i = 0; i < 10; i++)
cout << arr[i] << endl;
//释放堆区数组
delete[] arr;
}
int main()
{
//test01();
test02();
}
引用
#include<iostream>
using namespace std;
//值传递
void swap01(int a, int b)
{
int temp = a;
a = b;
b = temp;
}
//地址传递
void swap02(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
//引用传递
void swap03(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int a = 10, b = 20;
swap01(a, b); //形参不会修饰实参,实参不改变
cout << "a=" << a << endl;
cout << "b=" << b << endl;
swap02(&a, &b); //地址传递改变实参
cout << "a=" << a << endl;
cout << "b=" << b << endl;
swap03(a, b); //引用传递形参也可以修饰实参
cout << "a=" << a << endl;
cout << "b=" << b << endl;
}
#include<iostream>
using namespace std;
//引用做函数返回值
//1. 不要返回局部变量的引用
int& test01()
{
int a = 10; //局部变量放在栈区
return a;
}
//2. 函数的调用可以作为左值
int& test02()
{
static int a = 10; //静态变量,存放在全局区,程序结束后由系统释放
return a;
}
int main()
{
int& ref = test01();
cout << ref << endl;
cout << ref << endl;
test02() = 1000;
return 0;
}
引用的本质:在C++内部实现是一个指针常量
函数重载
#include<iostream>
using namespace std;
//函数重载满足条件
//1.同一作用域
//2.函数名称相同
//3.函数参数类型不同,或者个数不同,或者顺序不同
//返回值不可以做为函数重载条件
void func()
{
cout << "xxxx" << endl;
}
void func(int a)
{
cout << "aaaaa" << endl;
}
void func(double b)
{
cout << "llll" << endl;
}
void func(int a,double b)
{
cout << "mmmmm" << endl;
}
void func(double a, int b)
{
cout << "qqqq" << endl;
}
int main()
{
func();
func(10);
func(10.1);
func(10, 0.1);
func(10.1, 10);
}
类和对象
C++面向对象三大特征:封装,继承,多态
封装
公共权限 public 成员类内可以访问,类外可以访问
保护权限 protected 成员类内可以范文,类外不可以访问
私有权限 private 成员类内可以范文,类外不可以访问
保护权限和私有权限在继承中体现出不同。儿子可以访问父亲中的保护内容,儿子不可以访问父亲的私有内容
struct和class区别
构造函数和析构函数
#include<iostream>
using namespace std;
//拷贝构造函数调用时机
class Person
{
public:
Person()
{
cout << "Person默认构造函数调用" << endl;
}
Person(int age)
{
cout << "Person含参构造函数调用" << endl;
m_Age = age;
}
Person(const Person & p)
{
cout << "Person拷贝构造函数调用" << endl;
m_Age = p.m_Age;
}
~Person()
{
cout << "Person析构函数调用" << endl;
}
int m_Age;
};
//1.使用一个已经创建完毕的对象来初始化一个新对象
void test01()
{
Person p1(20);
Person p2(p1);
cout << "年龄为:" << endl;
}
//2.值传递的方式给函数参数传值
void dowork(Person p)
{
}
void test02()
{
Person p;
dowork(p);
}
//3.值方式返回局部对象
Person dowork2()
{
Person p1;
return p1;
}
void test03()
{
Person p = dowork2();
}
int main()
{
test01();
test02();
test03();
return 0;
}
浅拷贝带来的问题:队取得内存重复释放
解决浅拷贝问题:使用深拷贝
静态成员
#include<iostream>
using namespace std;
//静态成员变量
class Person {
public:
//所有对象共享同一份数据
//编译阶段就分配内存
//类内声明,类外初始化操作
static int m_A;
//静态成员变量也有访问权限,private中static成员变量不能在类外访问
};
void test01()
{
Person p;
cout << p.m_A << endl;
Person p1;
p1.m_A = 200;
cout << p1.m_A << endl; //共享一份内存,数值改变
}
int Person::m_A = 100; //类外初始化
void test02()
{
//静态成员变量不属于某个对象,所有对象共享同一份数据
//静态成员变量有两种访问方式
//1.通过对象进行访问
Person p;
cout << p.m_A << endl;
//2.通过类名进行访问
cout << Person::m_A << endl;
}
int main()
{
//test01();
test02();
return 0;
}
#include<iostream>
using namespace std;
//静态成员函数
//所有对象共享同一个函数
//静态成员函数只能访问静态成员变量
class Person {
public:
//静态成员函数
static void func()
{
m_A = 100; //静态成员函数可以访问静态成员变量
//m_B = 200; 静态成员函数 不可以访问 非静态成员变量
cout << "static void func函数调用" << endl;
}
static int m_A; //静态成员变量
int m_B; //非静态成员变量
//静态成员函数也有访问权限
};
void test01()
{
//1.通过对象名访问
Person p;
p.func();
//2.通过类名访问
Person::func();
}
int main()
{
test01();
return 0;
}
C++对象模型+this指针
#include<iostream>
using namespace std;
//成员变量 和 成员函数 分开存储
class Person {
int m_A; //非静态成员变量4字节
static int m_B; //静态成员变量 不属于类对象
void func(){} //非静态成员
};
int Person::m_B = 0; //静态成员变量
void test01()
{
Person p;
//空对象占内存空间为:1
//C++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存位置
//每个空对象也应该有一个独一无二的内存地址
cout << "size of p =" << sizeof(p) << endl;
}
void test02()
{
Person p;
cout << "size of p =" << sizeof(p) << endl;
}
int main()
{
//test01();
test02();
return 0;
}
#include<iostream>
using namespace std;
class Person {
public:
Person(int age)
{
//this指针指向被调用成员函数所属对象
this->age = age;
}
void PersonAddAge(Person &p)
{
this->age += p.age;
}
int age;
};
//1.解决名称冲突
void test01()
{
Person p1(18);
cout << "p1的年龄为:" << p1.age << endl;
}
//2.返回对象本身用*this
void test02()
{
Person p1(10);
Person p2(10);
p2.PersonAddAge(p1);
cout << "p2的年龄为:" << p2.age << endl;
}
int main()
{
//test01();
test02();
return 0;
}
#include<iostream>
using namespace std;
//空指针调用成员函数
class Person {
public:
void showClassName()
{
cout << "this is Person class" << endl;
}
void showPersonAge()
{
//报错原因是因为传入的指针是为NULL
cout << "age=" <<this->m_Age << endl;
}
int m_Age;
};
void test01()
{
Person* p = NULL;
p->showClassName();
p->showPersonAge();
}
int main()
{
test01();
return 0;
}
const修饰成员函数
友元
#include<iostream>
#include<string>
using namespace std;
class Building {
//goodfriend全局函数是Buiding好朋友,可以访问Buiding中私有成员
friend void goodfriend(Building* building);
public:
Building()
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
string m_SittingRoom;
private:
string m_BedRoom;
};
//全局函数
void goodfriend(Building *building)
{
cout << "好朋友全局函数正在访问:" << building->m_SittingRoom << endl;
cout << "好朋友全局函数正在访问:" << building->m_BedRoom << endl; //友元可以访问私有成员
}
void test01()
{
Building building;
goodfriend(&building);
}
int main()
{
test01();
return 0;
}
#include<iostream>
using namespace std;
class Building;
class g {
public:
g();
void visit(); //访问Building中的属性
Building* building;
};
class Building
{
//g类是本类的好朋友,可以访问本类中私有成员
friend class g;
public:
Building();
string m_SittingRoom;
private:
string m_BedRoome;
};
//类外写成员函数
Building::Building()
{
m_SittingRoom = "客厅";
m_BedRoome = "卧室";
}
g::g()
{
//创建建筑物对象
building = new Building;
}
void g::visit()
{
cout << "好朋友正在访问:" << building->m_SittingRoom << endl;
cout << "好朋友正在访问:" << building->m_BedRoome << endl;
}
void test01()
{
g gg;
gg.visit();
}
int main()
{
test01();
return 0;
}
运算符重载
加号重载
#include<iostream>
using namespace std;
class Person
{
public:
//1.成员函数重载+
/*Person operator+(Person& p)
{
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}*/
int m_A;
int m_B;
};
//2.全局函数重载+
Person operator+(Person& p1, Person& p2)
{
Person temp;
temp.m_A = p1.m_A + p2.m_A;
temp.m_B = p1.m_B + p2.m_B;
return temp;
}
void test01()
{
Person p1;
p1.m_A = 10;
p1.m_B = 10;
Person p2;
p2.m_A = 10;
p2.m_B = 10;
Person p3 = p1 + p2;
cout << "p3.m_A=" << p3.m_A << endl;
cout << "p3.m_B=" << p3.m_B << endl;
}
int main()
{
test01();
return 0;
}
继承
下级别成员拥有上一级的共性+自己的特性,继承可以减少代码复杂度
#include<iostream>
using namespace std;
//继承实现页面
//公共页面
class BasePage
{
public:
void header()
{
cout << "123456" << endl;
}
void footer()
{
cout << "789987" << endl;
}
void left()
{
cout << "skjfwej" << endl;
}
};
//java页面继承
class java :public BasePage {
public:
void content()
{
cout << "java knowledge" << endl;
}
};
void test01()
{
java js;
js.content();
js.footer();
js.header();
js.left();
}
int main()
{
test01();
return 0;
}
私有成员只是在继承中被隐藏,仍然会被继承下去,占内存空间
继承中父类子类构造函数和析构函数调用顺序:先调用父类构造函数,子类构造函数,子类析构函数,父类析构函数
#include<iostream>
using namespace std;
class Base
{
public:
Base()
{
m_A = 100;
}
void func()
{
cout << "Base -func()" << endl;
}
int m_A;
};
class Son :public Base
{
public:
Son()
{
m_A = 200;
}
void func()
{
cout << "Son -func()" << endl;
}
int m_A;
};
//同名成员属性处理方式
void test01()
{
Son s;
cout << "子类m_A=" <<s.m_A<< endl;
cout << "父类m_A=" << s.Base::m_A << endl;
}
//同名函数处理方式
void test02()
{
Son s;
s.func(); //子类
s.Base::func(); //父类
}
int main()
{
//test01();
test02(); //子类成员函数调用
return 0;
}
菱形继承
菱形继承会产生二义性(使用virtual)
#include<iostream>
using namespace std;
//动物类
class Animal
{
public:
int m_Age;
};
//利用虚继承解决菱形继承问题
//继承之前加上关键字 virtual 变为虚继承
//Animal类称为虚基类
//羊类
class Sheep :virtual public Animal
{
};
//驼类
class Tuo :virtual public Animal
{
};
//羊驼类
class SheepTuo :public Sheep, public Tuo
{
};
void test01()
{
SheepTuo st;
st.Sheep::m_Age = 18;
st.Tuo::m_Age = 28;
//菱形继承,两个父类拥有相同数据,需要加以作用域区分
cout << "st.Sheep::m_Age =" << st.Sheep::m_Age << endl;
cout << "st.Tuo::m_Age =" << st.Tuo::m_Age << endl;
//菱形继承导致数据有两份,我们只需要一份
}
int main()
{
test01();
return 0;
}
多态
#include<iostream>
using namespace std;
//纯虚函数和抽象类
class Base {
public:
//纯虚函数(只要有一个纯虚函数,这个类为抽象类)
//抽象类特点:
//1.无法实例化对象
//2.抽象类的子类,必须重写父类中的纯虚函数
virtual void func() = 0;
};
class Son :public Base
{
public:
virtual void func() {
cout << "func函数调用" << endl;
};
};
void test01()
{
//Son s;
Base* base = new Son;
base->func();
}
int main()
{
test01();
return 0;
}
构造函数与析构函数
文件操作
文本文件
#include<iostream>
#include<fstream>
using namespace std;
void test()
{
//包含头文件fstream
//创建流对象
ofstream ofs;
//指定打开方式
ofs.open("testtxt", ios::out);
//写内容
ofs << "姓名:张三" << endl;
//关闭文件
ofs.close();
}
int main()
{
test01();
return 0;
}
二进制文件
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。