拷贝构造函数调用几种情况
// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include "string.h"
#pragma warning(disable:4996)
using namespace std;
class Person{
public:
Person(){
cout << "构造函数" << endl;
}
~Person(){
cout << "析构造函数" << endl;
}
Person(const Person &p1)
{
cout << "拷贝构造函数" << endl;
}
};
void testCopyConstruct(Person p){
cout << "hello" << endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
// 调用拷贝构造函数的几种情况
Person person1;
//1. 情况1
Person person2 = person1;
// person2=person1 这种重载,和拷贝构造函数无关, 但是这里也是执行浅拷贝
// 2. 情况2
Person pp3(person1);
// pp3.setName("xiaoming");
// 3. 情况3
testCopyConstruct(pp3);
getchar();
return 0;
}
深拷贝:
// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include "string.h"
#pragma warning(disable:4996)
using namespace std;
class Person{
private:
char* name;
int age;
public:
Person(){
cout << "构造函数" << endl;
name = new char[100];
}
~Person(){
delete[]name;
cout << "析构造函数" << endl;
}
Person(const Person &p1)
{
// 默认拷贝
age = p1.age;
// 深拷贝
// 重新分配内存,避免
// 如果是默认 name= p1.name , 出现问题:person和person2共同指向同一块内存
// 如果一个对象A释放,那么对象B也释放,B在访问,出错
// 如果修改A对象的值,那么B对象的值也会改变
// 如果类中有指针,必须使用深拷贝
name = new char[100];
strcpy(name, p1.name);
cout << "拷贝构造函数" << endl;
}
void Person::setName(const char* s){
strcpy(name, s);
}
char* Person::getName(){
return name;
}
int getAge(){
return this->age;
}
void setAge(int _age){
this->age = _age;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Person person;
person.setName("xiaoming");
person.setAge(1000);
Person person2 = person;
cout << person2.getName() << person2.getAge() << endl;
getchar();
return 0;
}
静态变量:
// 8. 静态变量
cout << Person::account << endl;
友元函数、有元类
// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include "string.h"
#pragma warning(disable:4996)
using namespace std;
class Person{
private:
char* name;
int age;
friend class B; // B 是Person类的好朋友
public:
Person(){
cout << "构造函数" << endl;
name = new char[100];
}
~Person(){
delete[]name;
cout << "析构造函数" << endl;
}
void Person::setName(const char* s){
strcpy(name, s);
}
char* Person::getName(){
return name;
}
int getAge(){
return this->age;
}
void setAge(int _age){
this->age = _age;
}
// 友元函数,修改类的私有属性,在类中声明
friend void FriendFun(Person* p, int a);
};
// 友元函数,修改类的私有属性,在类的外部修改
void FriendFun(Person* p, int a){
p->age = a;
}
// 友元类,B 中的方法都可以修改Person中的私有属性
class B {
private:
Person p;
public:
void setA(){
p.age = 20555000;
}
void printA(){
cout << "friend class..." << p.age << endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
// 有元函数
Person* person = new Person();
FriendFun(person, 2000);
cout << person->getAge() << endl;
// 有元类
B b;
b.setA();
b.printA();
getchar();
return 0;
}
全局变量:
extern int person1;
// 5. 使用外部变量
// c++ 定义全局变量都不会在头文件中定义,在头文件中定义如果头文件被引用2次,会编译2次,出错
// 在.cpp中定义 如果要使用extern 引用即可
cout <<"all val " << person1 << endl;
命令空间:
// 8. 命名空间
namespace denganzhi {
int a=1000;
}
cout << denganzhi::a << endl;
堆栈:
// 2.基本类型new+delete 在基本类型、数组中使用
// new和 malloc区别: new会调用 构造函数 malloc 不会
// delete 和 free : delete会调用析构函数, free 不会
int* p1=new int(20);
cout << *p1 << endl;
delete p1;
// 数据类型释放内存 -- delete []p2
int* p2=new int[10];
for(int i=0;i<10;i++){
p2[i]=i;
}
for(int i=0;i<10;i++){
cout << p2[i] << endl;
}
delete []p2;
// 6. 类定义+构造函数
// 在栈中
// Person person("xiaoming");
// cout << person.getName() <<endl;
// 在堆中
// Person* person2=new Person("duidui");
// cout << person2->getName() <<endl;
// delete person2;
函数要点:
// 函数扩展:
// 1. c++ 函数支持默认参数,有形参和占位参数时候,默认参数必须在右边
// 2. 函数重载: 参数个数、类型、顺序不同和返回值无关,函数名相同
// 3. c++ 函数概念
1.c++ 引用
// 3. 引用
// c++中 函数参数是类,用引用,避免深拷贝,效率低
// 引用的优点:避免像普通函数参数或者指针一样入栈出栈,提高效率
int a1=30;
int& b1= a1; //引用,a1和b1地址完全相同
//
struct Teacher
{
char name[64];
int age ;
};
// 测试常引用
void printTeacher(const Teacher &t){
// t 只读
cout << t.name << endl;
}
int main0001()
{
// 常引用
Teacher t1;
strcpy(t1.name,"aa");
printTeacher(t1);
}
1. 返回堆内存
struct Teacher
{
char name[64];
int age ;
};
//在被调用函数 获取资源
int getTeacher(Teacher **p)
{
Teacher *tmp = NULL;
if (p == NULL)
{
return -1;
}
tmp = (Teacher *)malloc(sizeof(Teacher));
if (tmp == NULL)
{
return -2;
}
tmp->age = 33;
// p是实参的地址 *实参的地址 去间接的修改实参的值
*p = tmp;
}
//指针的引用 做函数参数
int getTeacher2(Teacher* &myp)
{
//给myp赋值 相当于给main函数中的pT1赋值
myp = (Teacher *)malloc(sizeof(Teacher));
if (myp == NULL)
{
return -1;
}
myp->age = 36;
}
void FreeTeacher(Teacher *pT1)
{
if (pT1 == NULL)
{
return ;
}
free(pT1);
}
int main0001()
{
Teacher *pT1 = NULL;
//1 c语言中的二级指针
getTeacher(&pT1);
cout<<"age:"<<pT1->age<<endl;
FreeTeacher(pT1);
//2 c++中的引用 (指针的引用)
//引用的本质 间接赋值后2个条件 让c++编译器帮我们程序员做了。
getTeacher2(pT1);
cout<<"age:"<<pT1->age<<endl;
FreeTeacher(pT1);
return 0;
}
1. c++ 继承
#include "iostream"
#include "string.h"
using namespace std;
class Parent{
/** 访问修饰符:
* private: 只能在内的内部使用
* protected: 类的内部,子类
* public: 外部类
*/
public:
virtual void print(){
cout << "father..." << endl;
}
Parent(){
}
Parent(int a,int b){
this->a=a;
this->b=b;
name= new char[100];
strcpy(name,"father...");
}
virtual ~Parent(){
cout << "Parent~" << endl;
delete []name;
}
public:
int a;
int b;
char* name;
};
class Child : public Parent{
private:
int c;
char* ch;
public:
Child(){
}
Child(int a,int b,int c): Parent(a,b){
this->c=c;
ch =new char[100];
strcpy(ch,"child");
}
/**
* 父子类使用virtual叫做重写父类的方法
* 如果没有使用virtual那么叫做重定义
*/
virtual void print(){
cout << "a:"<< this->a << "b" << this->b << "c" << this->c << endl;
}
void printFather(){
//子类访问父类属性
cout<< Parent::a << endl;
}
~Child(){
cout << "Child~" << endl;
delete []ch;
}
};
void mutifyMethod(Parent* p){
/**
* c++ 虚函数通过VPTR指针,里面有虚函数表(记住即可)
* 这里调用的是子类的方法
*/
p->print();
}
void deleteParent(Parent* p){
delete p;
}
class Father
{
public:
Father() {}
virtual void showMsg()=0; //纯虚函数,有纯虚函数的类叫做抽象类,抽象类不能被实例化
void showHello();
};
class Son: public Father{
public:
virtual void showMsg(){
cout <<"implements..father" << endl;
}
};
int main001(){
// Child child(1,2,3);
// child.print();
// child.printFather();
// cout << child.Parent::a<< endl;
// mutifyMethod(&child);
// Child* child=new Child();
// deleteParent(child);
Son son;
son.showMsg();
return 0;
}
1.模板c++
#include "iostream"
#include "string.h"
#include "complex.hpp"
using namespace std;
//1. 函数模板
template <typename T>
void myswap(T &a,T &b){
T c;
c=a;
a=b;
b=c;
}
// 2.类模板
template <typename T>
class A{
public:
A(T a){
this->a=a;
}
void print(){
cout <<"class Template... " << this->a <<endl;
}
public:
T a;
};
// 3.继承的时候,必须明确化泛型
// 子类必须要实例化父类构造函数
class B : public A<int>{
public:
B(int a=10):A<int>(a){
}
void print(){
cout <<"class Template... " << this->a <<endl;
}
};
// 4.从模板类中 派生模板类
template<typename T>
class C : public A<T>{
public:
C(T a):A<T>(a){
this->a=a;
}
friend ostream& operator<<(ostream& os,C<T>& c){
os << c.a << endl;
return os;
}
static T c_a;
};
//template<typename T>
//ostream& operator<<(ostream& os,C<T>& c){
// os << c.a << endl;
// return os;
//}
template<typename T>
T C<T>::c_a=4000;
int main0000001(){
int x=10;
int y=11;
myswap<int>(x,y); //调用函数模板
// myswap(x,y): 这样调用也可以会自动类型推导
cout << "x:" << x<<endl;
// 使用类模板
A<int> a(2222);
a.print();
B b(10);
b.print();
C<char> c('C');
c.print();
// 问题:无法解决, 类中重载<< 运算符
C<int> c1(20);
cout << c1 ;
// 如果类模板中.h和.cpp分开实现
// 那么把.cpp改成.hpp, 不用引入.h,需要引入.hpp
Complex<int> complex(1,2);
// cout << complex ; //错误
cout << "static" << C<int>::c_a <<endl;
return 0;
}
1. IO流
// c++ IO流
// int myInt;
// cin >> myInt;
// cout << myInt << endl; // 不可以接收空格
// char buf1[1024];
// cin.getline(buf1,1024); //可以接收空格
// cout << buf1 << endl;
// 文件流
// ios:app: 追加方式打开文件
// ios:out: 输出方式打开,覆盖
char *fname="C:\\1.txt";
ofstream fout(fname,ios::app);
fout << "hell .. 1 " << endl;
fout << "hell .. 2 " << endl;
fout.close();
ifstream fin(fname);
char ch;
while(fin.get(ch)){
// cout << ch ;
}
fin.close();
// ios::binary: 打开二进制文件
char *fname1="C:\\2.txt";
ofstream fout1(fname1,ios::app | ios::binary);
if(!fout1){
cout << "open file fail" <<endl;
return 0;
}
Teacher t1(1,2);
Teacher t2(2,3);
fout1.write((char*)&t1,sizeof(Teacher));
fout1.write((char*)&t2,sizeof(Teacher));
fout1.close();
Teacher temp;
//读文件
ifstream fin1(fname1);
fin1.read((char*)&temp,sizeof(Teacher));
temp.print();
fin1.read((char*)&temp,sizeof(Teacher));
temp.print();
fin1.close();
1. 异常
void divide(int y){
if(y==0){
throw y; // 抛出异常
}else if(y==1){
throw BadSrcException();
}
}
class BadSrcException : public exception{
public:
BadSrcException(){}
~BadSrcException(){}
virtual char const* what() const{
return "myexception";
}
};
int main1111(){
// 异常基础语法
try{
divide(1);
}catch(int y){
cout <<"y:" << y <<endl;
}catch (BadSrcException& badSrcExce){
cout << badSrcExce.what() << endl;
}catch(...){
cout <<"unknown exception" <<endl;
}
}
1. STL语法以及算法
#include "iostream"
#include "string.h"
#include "fstream"
#include "vector"
#include "deque"
#include "stack"
#include "queue"
#include "list"
#include "set"
#include "map"
#include "algorithm"
using namespace std;
int main09(){
// stl:惠普实验室开发的
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.insert(v1.begin(),0); // 在头部插入
// 区间删除
// v1.erase(v1.begin(),v1.begin()+1);
// *it 是指针,iterator迭代器
// for(vector<int>::iterator it=v1.begin();it!=v1.end();it++){
// cout << (*it) << endl;
// }
// for(int i=0;i<v1.size();i++){
// cout << v1[i] << endl;
// }
// 数据遍历的时候删除
for(vector<int>::iterator it=v1.begin();it!=v1.end();){
if(*it==3){
it= v1.erase(it); // 表示新位置
}else{
it++;
}
}
for(int i=0;i<v1.size();i++){
// cout << v1[i] << endl;
}
// 双向队列
deque<int> d1;
d1.push_back(1); //尾部插入
d1.push_back(2);
d1.push_front(3); //头部插入
for(deque<int>::iterator it=d1.begin();it!=d1.end();it++){
cout << *it <<endl;
}
d1.pop_back(); // 尾部弹出
d1.pop_front(); //头部弹出
cout << "operator then...." <<endl;
for(deque<int>::iterator it=d1.begin();it!=d1.end();it++){
cout << *it <<endl;
}
// stack栈
stack<int> s1;
for(int i=0;i<10;i++){
s1.push(i); //入栈
}
while(!s1.empty()){
int tmp= s1.top(); //获取栈顶元素
cout <<"stack: " << tmp << endl;
s1.pop(); //弹出栈顶元素
}
// queue,单向队列
queue<int> q1;
q1.push(10);
q1.push(11);
while(!q1.empty()){
cout << "deque"<< q1.front() << endl;
// cout << "deque "<< q1.back() << endl;
q1.pop();
}
// list, 双向链表
list<int> list1;
for(int i=0;i<5;i++){
list1.push_back(i);
}
// list1.insert(list1.begin(),100);
list<int>::iterator begin1= list1.begin();
list<int>::iterator begin2= list1.begin();
begin2++;
begin2++;
list1.erase(begin1,begin2); //删除指定区间元素
list1.remove(4);
for(list<int>::iterator it=list1.begin();it!=list1.end();it++){
cout << "list:" << *it << endl;
}
// set容器,集合中元素唯一
// muliset: 值可以重复
set<int> set1;
for(int i=0;i<5;i++){
set1.insert(i);
}
for(set<int>::iterator it=set1.begin();it!=set1.end();it++){
cout << "set..." << *it << endl;
}
// map 和 multimap(key可以重复)
map<int,string> map1;
map1.insert(pair<int,string>(1,"xiaoming"));
map1[2]="xiaohei";
map1.insert(pair<int,string>(3,"xiaozhe"));
for(map<int,string>::iterator it=map1.begin();it!=map1.end();it++){
cout << "map1..." << it->first << it->second << endl;
}
// map查找
map<int,string>::iterator it2= map1.find(2);
if(it2 == map1.end()){
cout << "key not save" << endl;
}else{
cout << "key exist " << it2->second << endl;
}
// map/set底层实现红黑树,初始化
map<int, string> map11 = { { 1, "A" }, { 2, "B" } };
map11.insert({ 3, "c" });
map11[4] = { "D" }; //key为3 , key不能重复
return 0;
}
class Student{
private:
int age;
public:
void setAge(int _age){
this->age=_age;
}
int getAge(){
return this->age;
}
Student(int _age){
this->age=_age;
}
Student(){
}
};
bool CompareS(Student& s1,Student& s2){
return (s1.getAge()>s2.getAge());
}
// STL常用算法
int main(){
vector<int> v1;
v1.push_back(1);
// vector<int> v2;
// v2.push_back(2);
// vector<int> v3;
// v3.resize(v1.size()+v2.size());
// merge(v1.begin(),v1.end(),v2.begin(),v2.end(),v3.begin());
// for(vector<int>::iterator it=v3.begin();it!=v3.end();it++){
// cout << *it << endl;
// }
// Student s1(10);
// Student s2(20);
// Student s3(15);
// vector<Student> ss;
// ss.push_back(s1); ss.push_back(s2); ss.push_back(s3);
// sort(ss.begin(),ss.end(),CompareS);
// reverse(ss.begin(),ss.end());
// for(vector<Student>::iterator it=ss.begin();it!=ss.end();it++){
// cout << "ss: " << it->getAge() << endl;
// }
vector<int> v4;
v4.resize(v1.size());
copy(v1.begin(),v1.end(),v4.begin());
for(vector<int>::iterator it=v4.begin();it!=v4.end();it++){
cout << "v4: " << *it << endl;
}
return 0;
}