构造函数、析构函数
# include <iostream>
using namespace std;
class Person
{
private :
int age;
public :
Person ( )
{
cout << "构造函数的调用,无参" << endl;
}
Person ( int a)
{
age = a;
cout << "构造函数的调用, 含参" << endl;
}
Person ( const Person& p)
{
this -> age = p. age;
cout << "构造函数的调用,拷贝" << endl;
}
~ Person ( )
{
cout << "析构函数的调用" << endl;
}
int getAge ( ) { return age; }
} ;
void test ( )
{
Person p1;
Person p2 = Person ( 10 ) ;
Person p3 = Person ( p2) ;
Person p4 = 10 ;
Person p5 = p4;
}
int main ( )
{
test ( ) ;
}
初始化列表
# include <iostream>
using namespace std;
class Person
{
public :
int age;
int height;
Person ( int a, int b) : age ( a) , height ( b)
{
;
}
} ;
void test ( )
{
Person man ( 28 , 180 ) ;
cout << man. age << endl << man. height << endl;
}
int main ( )
{
test ( ) ;
}
常函数、常对象
# include <iostream>
using namespace std;
class Person
{
public :
void showPerson ( ) const
{
age = 30 ;
height = 180 ;
}
void change ( )
{
age = 40 ;
height = 166 ;
}
int age;
mutable int height;
} ;
void test1 ( )
{
Person p;
p. showPerson ( ) ;
}
void test2 ( )
{
const Person p;
p. age = 22 ;
p. height = 175 ;
p. showPerson ( ) ;
p. change ( ) ;
}
int main ( )
{
test1 ( ) ;
test2 ( ) ;
}
运算符重载
+ 运算符 重载
# include <iostream>
using namespace std;
class Person
{
public :
int age;
int height;
Person operator + ( const Person & p)
{
Person temp;
temp. age = this -> age + p. age;
temp. height = this -> height + p. height;
return temp;
}
} ;
Person operator + ( const Person& p1, const Person& p2)
{
Person temp;
temp. age = p1. age + p2. age;
temp. height = p1. height + p2. height;
return temp;
}
void test ( )
{
Person p1;
p1. age = 22 ;
p1. height = 166 ;
Person p2;
p2. age = 28 ;
p2. height = 134 ;
Person p3 = p1 + p2;
cout << p3. age << endl << p3. height << endl;
Person p3 = p3 + 66 ;
}
int main ( )
{
test ( ) ;
}
<< 运算符 重载
# include <iostream>
using namespace std;
class Person
{
friend ostream& operator << ( ostream& , const Person& ) ;
public :
Person ( int age, int height) : age ( age) , height ( height)
{
cout << "调用了构造函数" << endl;
}
private :
int age;
int height;
} ;
ostream& operator << ( ostream& cout, const Person& p)
{
cout << "[ age = " << p. age << ", height = " << p. height << " ]" ;
return cout;
}
void test ( )
{
Person p1 ( 22 , 166 ) ;
cout << p1 << endl;
}
int main ( )
{
test ( ) ;
}
自增运算符 重载
#include <iostream>
using namespace std;
class MyInteger
{
friend ostream& operator<<(ostream&, MyInteger);
public:
MyInteger(int a) :num(a)
{
cout << "调用了构造函数" << endl;
}
// 前置递增
MyInteger& operator++()
{
num++;
return *this;
}
// 后置递增
MyInteger operator++(int) // int 代表占位参数,可以用于区分前置和后置递增
{
// 先记录当前结果
MyInteger temp = *this;
// 后将自己进行递增
num++;
return temp;
}
private:
int num;
};
ostream& operator<<(ostream& cout, MyInteger obj)
{
cout << obj.num;
return cout;
}
void test()
{
MyInteger myint = 0;
cout << ++(++myint) << endl; // 输出:2
cout << myint << endl; // 输出:2
cout << myint++ << endl; // 输出:2
cout << myint<< endl; // 输出:3
}
int main()
{
test();
}
赋值运算符 重载
#include <iostream>
using namespace std;
class Person
{
public:
Person(int age)
{
this->age = new int(age);
}
~Person()
{
if (age != NULL)
{
delete age;
age = NULL;
}
}
// 赋值运算符重载
Person& operator=(const Person& obj)
{
*age = *obj.age;
return *this;
}
int* age;
};
void test()
{
Person p1(10);
cout << "p1的年龄为:" << *p1.age << endl; // 输出结果:10
Person p2(20);
cout << "p2的年龄为:" << *p2.age << endl; // 输出结果:20
Person p3(30);
cout << "p3的年龄为:" << *p3.age << endl; // 输出结果:30
// 这不是拷贝构造函数,拷贝构造函数也是一种构造函数
// 这里是赋值语句,对象的赋值,编译器默认的行为是:将某对象的所有属性复制一份到另一个对象里面
// 因为默认行为的直接复制,对于需要浅拷贝的内容没什么影响,但是对于需要深拷贝的内容影响很大
// 为了避免恶劣影响,我们需要重载赋值运算符
p3 = p2 = p1;
cout << "修改后的p2的年龄为:" << *p2.age << endl; // 输出结果:10
cout << "修改后的p3的年龄为:" << *p3.age << endl; // 输出结果:10
}
int main()
{
test();
}
关系运算符 重载
# include <iostream>
# include <string>
using namespace std;
class Person
{
public :
string name;
int age;
Person ( string name, int age) : name ( name) , age ( age)
{
;
}
bool operator == ( const Person& obj)
{
if ( name == obj. name && age == obj. age)
{
return true ;
}
return false ;
}
bool operator != ( const Person& obj)
{
if ( name == obj. name && age == obj. age)
{
return false ;
}
return true ;
}
} ;
void test ( )
{
Person p1 ( "Jack" , 18 ) ;
Person p2 ( "Jack" , 18 ) ;
Person p3 ( "Tom" , 18 ) ;
if ( p1 == p2) cout << "p1 和 p2 相等" << endl;
if ( p1 != p3) cout << "p1 和 p3 不相等" << endl;
}
int main ( )
{
test ( ) ;
}
函数调用运算符 重载
#include <iostream>
#include <string>
using namespace std;
class MyPrint
{
public:
// 重载函数调用运算符
void operator()(string text, string end="\n")
{
cout << text << end;
}
};
class MyAdd
{
public:
// 重载函数调用运算符
int operator()(int a, int b)
{
return a + b;
}
};
void test()
{
MyPrint print;
MyAdd add;
print("hello world"); // 由于使用起来非常类似于函数调用,因此称为仿函数
string res = to_string(add(10, 20));
print(res);
// 匿名函数对象 -> MyAdd()
cout << MyAdd()(100, 100) << endl;
}
int main()
{
test();
}
继承知识补充
多态
基础应用
# include <iostream>
# include <string>
using namespace std;
class Animal
{
public :
virtual void speak ( )
{
cout << "动物在叫" << endl;
}
} ;
class Cat : public Animal
{
public :
void speak ( )
{
cout << "猫在叫" << endl;
}
} ;
class Dog : public Animal
{
public :
void speak ( )
{
cout << "狗在叫" << endl;
}
} ;
void doSpeak ( Animal& animal)
{
animal. speak ( ) ;
}
void test ( )
{
Cat cat;
Dog dog;
doSpeak ( cat) ;
doSpeak ( dog) ;
}
int main ( )
{
test ( ) ;
}
进阶应用
# include <iostream>
# include <string>
using namespace std;
class abstractDrinking
{
public :
virtual void Boil ( ) = 0 ;
virtual void Brew ( ) = 0 ;
virtual void PourInCup ( ) = 0 ;
virtual void PutSomething ( ) = 0 ;
void make ( )
{
Boil ( ) ;
Brew ( ) ;
PourInCup ( ) ;
PutSomething ( ) ;
}
} ;
class Coffee : public abstractDrinking
{
public :
virtual void Boil ( )
{
cout << "煮熟自来水" << endl;
}
virtual void Brew ( )
{
cout << "冲泡咖啡" << endl;
}
virtual void PourInCup ( )
{
cout << "倒入迷你的咖啡杯中" << endl;
}
virtual void PutSomething ( )
{
cout << "加入一些糖" << endl;
}
} ;
class Tea : public abstractDrinking
{
public :
virtual void Boil ( )
{
cout << "煮熟矿泉水" << endl;
}
virtual void Brew ( )
{
cout << "冲泡茶叶" << endl;
}
virtual void PourInCup ( )
{
cout << "倒入经典的茶杯中" << endl;
}
virtual void PutSomething ( )
{
cout << "加入一些香料" << endl;
}
} ;
void makeDrink ( abstractDrinking* drink)
{
drink-> make ( ) ;
delete drink;
}
void test ( )
{
makeDrink ( new Coffee) ;
makeDrink ( new Tea) ;
}
int main ( )
{
test ( ) ;
}
高级应用 (经典)
# include <iostream>
# include <string>
using namespace std;
class CPU
{
public :
virtual void calculate ( ) = 0 ;
} ;
class VideoCard
{
public :
virtual void display ( ) = 0 ;
} ;
class Memory
{
public :
virtual void storage ( ) = 0 ;
} ;
class IntelCPU : public CPU
{
public :
virtual void calculate ( )
{
cout << "Intel 的 CPU 开始工作了" << endl;
}
} ;
class IntelVideoCard : public VideoCard
{
public :
virtual void display ( )
{
cout << "Intel 的 VideoCard 开始工作了" << endl;
}
} ;
class IntelMemory : public Memory
{
public :
virtual void storage ( )
{
cout << "Intel 的 Memory 开始工作了" << endl;
}
} ;
class LenovoCPU : public CPU
{
public :
virtual void calculate ( )
{
cout << "Lenovo 的 CPU 开始工作了" << endl;
}
} ;
class LenovoVideoCard : public VideoCard
{
public :
virtual void display ( )
{
cout << "Lenovo 的 VideoCard 开始工作了" << endl;
}
} ;
class LenovoMemory : public Memory
{
public :
virtual void storage ( )
{
cout << "Lenovo 的 Memory 开始工作了" << endl;
}
} ;
class Computer
{
public :
Computer ( CPU* cpu, VideoCard* vc, Memory* mem) : cpu ( cpu) , vc ( vc) , mem ( mem)
{
;
}
void work ( )
{
cpu-> calculate ( ) ;
vc-> display ( ) ;
mem-> storage ( ) ;
}
~ Computer ( )
{
if ( cpu != NULL )
{
delete cpu;
cpu = NULL ;
}
if ( vc != NULL )
{
delete vc;
vc = NULL ;
}
if ( mem != NULL )
{
delete mem;
mem = NULL ;
}
}
private :
CPU* cpu;
VideoCard* vc;
Memory* mem;
} ;
void test ( )
{
CPU* intelCpu = new IntelCPU;
VideoCard* intelCard = new IntelVideoCard;
Memory* intelMem = new IntelMemory;
Computer* computer1 = new Computer ( intelCpu, intelCard, intelMem) ;
computer1-> work ( ) ;
delete computer1;
computer1 = NULL ;
cout << "------------------------------" << endl;
Computer* computer2 = new Computer ( new LenovoCPU, new LenovoVideoCard, new LenovoMemory) ;
computer2-> work ( ) ;
delete computer2;
computer2 = NULL ;
cout << "------------------------------" << endl;
Computer* computer3 = new Computer ( new IntelCPU, new LenovoVideoCard, new LenovoMemory) ;
computer3-> work ( ) ;
delete computer3;
computer3 = NULL ;
}
int main ( )
{
test ( ) ;
}
文件操作
# include <iostream>
# include <fstream>
# include <string>
using namespace std;
void writeText ( )
{
ofstream file;
file. open ( "test.txt" , ios:: app) ;
file << "姓名:张三" << endl;
file << "性别:男" << endl;
file << "年龄:28" << endl;
file. close ( ) ;
}
void readText ( )
{
ifstream file;
file. open ( "test.txt" , ios:: in) ;
if ( ! file. is_open ( ) )
{
cout << "文件打开失败!" << endl;
return ;
}
char c;
while ( ( c = file. get ( ) ) != EOF )
{
cout << c;
}
file. close ( ) ;
}
class Person
{
public :
char m_Name[ 64 ] ;
int m_Age;
} ;
void writeBinary ( )
{
ofstream file;
file. open ( "person.txt" , ios:: out | ios:: binary) ;
Person p = { "张三" , 28 } ;
file. write ( ( const char * ) & p, sizeof ( Person) ) ;
file. close ( ) ;
}
void readBinary ( )
{
ifstream file;
file. open ( "person.txt" , ios:: in | ios:: binary) ;
if ( ! file. is_open ( ) )
{
cout << "文件打开失败" << endl;
}
Person p;
file. read ( ( char * ) & p, sizeof ( Person) ) ;
cout << "姓名:" << p. m_Name << "年龄:" << p. m_Age << endl;
file. close ( ) ;
}
int main ( )
{
writeText ( ) ;
readText ( ) ;
writeBinary ( ) ;
readBinary ( ) ;
}
函数模板的重载
# include <iostream>
# include <string>
using namespace std;
class Person
{
public :
Person ( string name, int age)
{
this -> m_Name = name;
this -> m_Age = m_Age;
}
string m_Name;
int m_Age;
} ;
template < typename T >
bool myCompare ( T & a, T & b)
{
if ( a == b) return true ;
else return false ;
}
template < >
bool myCompare ( Person& p1, Person& p2)
{
if ( p1. m_Name == p2. m_Name && p1. m_Age == p2. m_Age) return true ;
else return false ;
}
void test ( )
{
int a = 10 ;
int b = 10 ;
bool ret = myCompare ( a, b) ;
cout << ret << endl;
Person p1 ( "张三" , 18 ) ;
Person p2 ( "李四" , 28 ) ;
bool res = myCompare ( p1, p2) ;
cout << res << endl;
}
int main ( )
{
test ( ) ;
}
类模板
# include <iostream>
# include <string>
using namespace std;
template < class Type1 , class Type2 = int >
class Person
{
public :
Person ( Type1 name, Type2 age)
{
this -> m_Name = name;
this -> m_Age = age;
}
void showPerson ( )
{
cout << "name: " << m_Name << " age: " << m_Age << endl;
}
Type1 m_Name;
Type2 m_Age;
} ;
void test ( )
{
Person< string, int > p1 ( "张三" , 18 ) ;
p1. showPerson ( ) ;
Person< string> p2 ( "李四" , 28 ) ;
p2. showPerson ( ) ;
}
int main ( )
{
test ( ) ;
}
# include <iostream>
# include <string>
using namespace std;
template < class T1 , class T2 >
class Person
{
public :
Person ( T1 name, T2 age)
{
this -> m_Name = name;
this -> m_Age = age;
}
void showPerson ( )
{
cout << "姓名:" << this -> m_Name << " 年龄:" << this -> m_Age << endl;
}
T1 m_Name;
T2 m_Age;
} ;
void printPerson1 ( Person< string, int > & p)
{
p. showPerson ( ) ;
}
template < class T1 , class T2 >
void printPerson2 ( Person< T1, T2> & p)
{
p. showPerson ( ) ;
}
template < class T >
void printPerson3 ( T& p)
{
p. showPerson ( ) ;
}
void test ( )
{
Person< string, int > p1 ( "张三" , 28 ) ;
printPerson1 ( p1) ;
Person< string, int > p2 ( "李四" , 18 ) ;
printPerson2 ( p2) ;
Person< string, int > p3 ( "王五" , 38 ) ;
printPerson3 ( p3) ;
}
int main ( )
{
test ( ) ;
}
类模板与继承
#include <iostream>
#include <string>
using namespace std;
// 类模板与继承
template <class T>
class Base
{
T m_Name;
};
// 必须要知道父类中的T类型,才能继承给子类
class Son : public Base<int>
{
};
void test1()
{
Son s1;
}
// 如果想灵活指定父类中T类型,子类也需要变类模板
template <class T1, class T2>
class Son2 : public Base<T2>
{
public:
Son2()
{
cout << "T1 的类型为:" << typeid(T1).name() << endl;
cout << "T2 的类型为:" << typeid(T2).name() << endl;
}
};
void test2()
{
Son2<int, char> s2;
}
int main()
{
test1();
test2();
}
类模板函数的类外实现
#include <iostream>
#include <string>
using namespace std;
template<class T1, class T2>
class Person
{
public:
Person(T1 name, T2 age);
void showPerson();
T1 m_Name;
T2 m_Age;
};
// 类模板成员的类外实现(构造函数)
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) :m_Name(name), m_Age(age)
{
cout << "构造函数被调用了" << endl;
}
// 类模板成员的类外实现(普通成员函数)
template<class T1, class T2>
void Person<T1, T2>::showPerson()
{
cout << "姓名:" << m_Name << "年龄:" << m_Age;
}
void test()
{
Person<string, int> p("Tom", 28);
}
int main()
{
test();
}
类模板分文件编写
问题:
类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到
解决:
解决办法1 :直接包含. cpp源文件
解决办法2 :将声明和实现写到同一个文件中,并更改后缀名为. hpp,. hpp是约定的名称,并不是强制
#include <string>
using namespace std;
// 第一种解决方式:直接包含源文件
#include "person.cpp"
// 第二种解决方式:将.h和.cpp中的内容写在一起,将后缀名改为.hpp文件(约定俗成)
// #include "person.hpp"
void test()
{
Person<string, int> p("Tom", 28);
p.showPerson();
}
int main()
{
test();
}
#include <iostream>
#include "person.h"
// 类模板成员的类外实现(构造函数)
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) :m_Name(name), m_Age(age)
{
std::cout << "构造函数被调用了" << std::endl;
}
// 类模板成员的类外实现(普通成员函数)
template<class T1, class T2>
void Person<T1, T2>::showPerson()
{
std::cout << "姓名:" << m_Name << " 年龄:" << m_Age << std::endl;
}
#pragma once // 只要在头文件的最开始加入这条预处理指令,就能够保证头文件只被编译一次,防止头文件被重复引用
template<class T1, class T2>
class Person
{
public:
Person(T1 name, T2 age);
void showPerson();
T1 m_Name;
T2 m_Age;
};
类模板与友元
# include <iostream>
# include <string>
using namespace std;
template < class T1 , class T2 >
class Person ;
template < class T1 , class T2 >
void printPerson2 ( Person< T1, T2> p)
{
cout << "姓名:" << p. m_Name << " 年龄:" << p. m_Age << endl;
}
template < class T1 , class T2 >
class Person
{
friend void printPerson ( Person< T1, T2> p)
{
cout << "姓名:" << p. m_Name << " 年龄:" << p. m_Age << endl;
}
friend void printPerson2 < > ( Person< T1, T2> p) ;
public :
Person ( T1 name, T2 age) : m_Name ( name) , m_Age ( age)
{
cout << "成功构造了一个对象" << endl;
}
private :
T1 m_Name;
T2 m_Age;
} ;
void test ( )
{
Person< string, int > p1 ( "Jack" , 29 ) ;
printPerson ( p1) ;
Person< string, int > p2 ( "Tom" , 30 ) ;
printPerson2 ( p2) ;
}
int main ( )
{
test ( ) ;
}
模板案例
# include <iostream>
# include <string>
# include "MyArray.hpp"
using namespace std;
void test1 ( )
{
MyArray< int > arr1 ( 10 ) ;
MyArray< int > arr2 = arr1;
MyArray< int > arr3 ( 20 ) ;
arr3 = arr1;
bool ret;
for ( int i = 0 ; i < arr3. getCapacity ( ) ; i++ )
{
ret = arr3. append ( 100 - i) ;
cout << ret << endl;
}
cout << "----------" << endl;
arr3. pop ( ) ;
cout << arr3[ 9 ] << endl;
arr3[ 9 ] = 666 ;
cout << arr3[ 9 ] << endl;
}
class Person
{
public :
Person ( ) { }
Person ( string name, int age)
{
this -> m_Name = name;
this -> m_Age = age;
}
string m_Name;
int m_Age;
} ;
void test2 ( )
{
MyArray< Person> arr ( 3 ) ;
Person p1 ( "Jack" , 25 ) ;
Person p2 ( "Tom" , 28 ) ;
Person p3 ( "Jim" , 29 ) ;
arr. append ( p1) ;
arr. append ( p2) ;
arr. append ( p3) ;
for ( int i = 0 ; i < arr. getCapacity ( ) ; i++ )
{
cout << "姓名:" << arr[ i] . m_Name << "\t年龄:" << arr[ i] . m_Age << endl;
}
}
int main ( )
{
test1 ( ) ;
cout << "*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*" << endl;
test2 ( ) ;
system ( "pause" ) ;
return 0 ;
}
# pragma once
# include <iostream>
# include <string>
template < class T >
class MyArray
{
private :
T* pAddress;
int m_Capacity;
int m_Size;
public :
MyArray ( int capacity)
{
this -> m_Capacity = capacity;
this -> m_Size = 0 ;
this -> pAddress = new T[ this -> m_Capacity] ;
}
~ MyArray ( )
{
if ( this -> pAddress != NULL )
{
delete [ ] this -> pAddress;
this -> pAddress = NULL ;
}
}
MyArray ( const MyArray& arr)
{
this -> m_Capacity = arr. m_Capacity;
this -> m_Size = arr. m_Size;
this -> pAddress = new T[ arr. m_Capacity] ;
for ( int i = 0 ; i < arr. m_Size; i++ )
{
this -> pAddress[ i] = arr. pAddress[ i] ;
}
}
MyArray& operator = ( const MyArray& arr)
{
if ( this -> pAddress != NULL )
{
delete [ ] this -> pAddress;
this -> pAddress = NULL ;
this -> m_Capacity = 0 ;
this -> m_Size = 0 ;
}
this -> m_Capacity = arr. m_Capacity;
this -> m_Size = arr. m_Size;
this -> pAddress = new T[ arr. m_Capacity] ;
for ( int i = 0 ; i < arr. m_Size; i++ )
{
this -> pAddress[ i] = arr. pAddress[ i] ;
}
return * this ;
}
bool append ( const T& value)
{
if ( this -> m_Size == this -> m_Capacity) return false ;
this -> pAddress[ m_Size] = value;
m_Size++ ;
return true ;
}
void pop ( )
{
if ( this -> m_Size == 0 ) return ;
m_Size-- ;
}
T& operator [ ] ( int index)
{
return this -> pAddress[ index] ;
}
int getSize ( )
{
return this -> m_Size;
}
int getCapacity ( )
{
return this -> m_Capacity;
}
} ;