网站建设与管理教程,网站转化率是什么意思,sea wordpress 搭建,域名查询网138C疑难点
this指针
调用成员函数时#xff0c;成员函数通过一个名为 this 的隐式参数来访问调用它的那个对象#xff0c;用请求该函数的对象地址初始化 this #xff0c;this 的指向总是自己这个对象#xff0c;所以 this 是一个常量指针
Box* get_address() //得到thi…C疑难点
this指针
调用成员函数时成员函数通过一个名为 this 的隐式参数来访问调用它的那个对象用请求该函数的对象地址初始化 this this 的指向总是自己这个对象所以 this 是一个常量指针
Box* get_address() //得到this的地址
{return this;
}
Box* get_address() //得到this的地址
{Box box;this box; // error: lvalue required as left operand of assignmentreturn this;
}友元函数和运算符重载
#include iostream
#include cmath
using namespace std;class MyInteger
{
public:MyInteger() { this-num_ 0; }MyInteger(int num) : num_(num) {}MyInteger operator(const MyInteger other){MyInteger temp;temp.num_ this-num_ other.num_;// this-num_ m.num_; // 这违反了加法运算符的语义加法运算通常是创建一个新的对象来保存结果而不是改变原始对象。return temp;}MyInteger operator(const int other) // 运算符重载{MyInteger temp;temp.num_ this-num_ other;return temp;}MyInteger operator(const MyInteger other){MyInteger temp;temp.num_ this-num_ other.num_;return temp;}MyInteger operator(const int other){MyInteger temp;temp.num_ this-num_ other;return temp;}MyInteger operator(){num_;return *this;}MyInteger operator(int){MyInteger temp(*this);num_;return temp;}MyInteger operator(const MyInteger myInteger) // 注意深浅拷贝问题{num_ myInteger.num_;}friend ostream operator(ostream out, const MyInteger myInteger); // 重载左移运算符 没加 const cout m;报错private:int num_;
};ostream operator(ostream out, const MyInteger myInteger)
{out myInteger.num_;return out;
}void test01()
{MyInteger m;MyInteger m1(10);m1 m m1;cout m endl;cout m1 endl;
}void test02()
{MyInteger m(1);MyInteger m1(100);m m1 m;m1 10;cout m m1 endl;
}void test03()
{MyInteger m(2);MyInteger m1(8);// cout (m) m1 endl;// cout m ;cout m;cout m;
}int main()
{// test01();// test02();test03();// int a1;// int b2;// aab;// couta bendl;int c 1;cout endl;cout c endl;cout c endl;return 0;
}不能重载的运算符
.:: ?:sizeoftypeid.* 这几个运算符不能被重载
C编译器至少给一个类提供四个函数
1、构造函数
2、析构函数
3、拷贝构造函数
4、operator 函数
多态的实现
多态实现的前提三个条件
1、必须是共有继承
2、通过基类指针指向派生类并且访问派生类重写的方法。
3、基类中的被重写的方法是虚函数
这种技术让父类指针有多种形态是一种泛型技术直到运行时才决定执行哪个版本的函数。所谓泛型技术就是使用不变的代码来实现可变的算法。多态中没有重写的函数是没有意义的。
水能载舟亦能覆舟。多态也涉及了安全性的问题
首先是无法访问子类中自己的虚函数如Base * basenew Derived(); base-f1();编译时不会通过的其中f1()是子类自己的虚函数父类没有
然后是如果父类中虚函数是private或者protected这些函数依旧会存在于虚函数表中可以通过多态的方式来访问。
#include iostream
using namespace std;
class Father
{
public:virtual void f(){couthello Father!endl;}
};class Son : public Father
{
public:void f(){cout hello Son!endl;}
};int main() {Son s;Father *p s;p-f();Father f;pf;p-f();return 0;
}菱形继承的问题
继承关系画成图像一个菱形所以就叫做菱形继承采用虚继承来解决二义性问题。
虚析构
总的来说是为了避免内存泄漏当子类中有指针成员变量时才会使用到。也就是说虚析构函数使得删除指向子类的父类指针时不仅可以调用父类的的析构函数也会调用子类的析构函数这样就可以释放子类指针成员变量在堆中的内存达到防止内存泄漏的目的。
#include bits/stdc.h
using namespace std;
class CA
{
public:CA() { cout CA endl; }virtual void f1(){cout CA::f1( ) endl;// f2();}void f2(){cout CA::f2( ) endl;}virtual ~CA(){cout ~CA endl;}
};
class CB : public CA
{
public:CB() { cout CB endl; }virtual void f1(){cout CB::f1( ) endl;}void f2(){cout CB::f2( ) endl;}virtual ~CB(){cout ~CB endl;}
};
class CC : public CB
{
public:CC() { cout CC endl; }void f1(){coutCC:f1()endl;}void f2(){cout CC:f2() endl;}virtual ~CC(){cout ~CC endl;}
};
int main()
{CA *pA new CC();pA-f1();delete pA;CA *pA1 new CB();pA1-f1();delete pA;return 0;
}//注意看构造和析构的顺序正好是相反的g和gcc的区别
面试的时候问到了gcc和g的区别没答上来
首先说明gcc 和 GCC 是两个不同的东西
GCC:GNU Compiler Collection(GNU 编译器集合)它可以编译C、C、JAV、Fortran、Pascal、Object-C、Ada等语言。
gcc是GCC中的GNU C CompilerC 编译器
g是GCC中的GNU C CompilerC编译器
一个有趣的事实就是就本质而言gcc和g并不是编译器也不是编译器的集合它们只是一种驱动器根据参数中要编译的文件的类型调用对应的GUN编译器而已比如用gcc编译一个c文件的话会有以下几个步骤
Step1Call a preprocessor, like cpp.
Step2Call an actual compiler, like cc or cc1.
Step3Call an assembler, like as.
Step4Call a linker, like ld
由于编译器是可以更换的所以gcc不仅仅可以编译C文件
所以更准确的说法是gcc调用了C compiler而g调用了C compiler
gcc和g的主要区别 对于 .c和.cpp文件gcc分别当做c和cpp文件编译c和cpp的语法强度是不一样的 对于 .c和.cpp文件g则统一当做cpp文件编译 使用g编译文件时g会自动链接标准库STL而gcc不会自动链接STL gcc在编译C文件时可使用的预定义宏是比较少的 gcc在编译cpp文件时/g在编译c文件和cpp文件时这时候gcc和g调用的都是cpp文件的编译器
关于内联函数
一般是加快程序执行速度可能减小可执行文件大小可能增加可执行文件大小。
速度快当函数体较短时内敛函数会像宏一样展开所以执行速度比一般函数要快。但是如果函数体过大一般的编译器会放弃内联方式意思就是你使用内联函数只不过是向编译器提出了一个申请编译器可以拒绝这个函数又会像普通函数一样执行效率也和普通函数一样。
减小可执行文件大小内联函数适度
增加可执行文件大小内联函数过多
仿函数
在c中仿函数Functor是一个类或者结构体重载了函数调用运算符()它的主要作用是提供一种更加灵活的函数对象它可以包含状态信息并且可以被传递给算法或者函数从而实现定制的行为。比如实现排序准则、查找准则、谓词就是一个bool返回值的函数
#include iostream
#include vector
#include algorithm
using namespace std;void Print(int val){coutval ;}
class Print1
{
public:void operator()(int val){coutval ;}
};void test01()
{vectorint v;v.push_back(6);v.push_back(66);for_each(v.begin(), v.end(), Print1());coutendl--------------endl;for_each(v.begin(), v.end(), Print);
}int main()
{test01();return 0;
}pointer-like-class的作用
pointer-like-class是指类似指针的类这种类一般用来模拟指针的行为但是与裸指针相比具有更多的功能和安全性如智能指针Smart Pointers、迭代器Iterators。Smart Pointers有std::unique_ptr和std::shared_ptr、std::weak_ptr。
一结构化程序设计方法
位运算及其运用
判断奇数还是偶数
int a11;
int b1;
if(ba){cout is odd endl;
}else{cout is even endl;
}取出指定的位
int a0b11101101;
int b0b1111;
cout bitsetsizeof(char)*8(ab)endl;判断是否为2的整数幂0b10 0000 0b01 1111结果是0说明是2的整数幂。
int x 64;
int y x - 1;
cout ((x y) ? no : yes) endl;指针数组与指向数组的指针的概念与使用
a是一个指向含有三个int型数据数组的指针如有int p[3]; a指向p是可以的
a1是一个函数三个int*型数据的数组如a1可以初始化为{b, c, d};
#include iostream
#include typeinfo
using namespace std;
#define sz(type) coutsizeof(type)endl;
int main(){int b10, c1, d2;int (*a)[3];int* a1[3];couttypeid(a).name()endl;sz(a);sz(a1);sz(a1[0]);sz(*a)sz(a[0][0])return 0;
}引用的分类与使用
1、初始化定义引用时需要加
int a1;
int ba;//相当于给a取了一个别名2、作为函数参数传递c在函数参数中传递数组时直接变成了指针因为如果将数组传递过去需要将值一个一个拷贝过去增加了函数调用的开销所以在 C 中我们有了一种比指针更加便捷的传递聚合类型数据的方式那就是引用Reference通过这种方式传过去减少了生成副本的消耗。
void swap(int a, int b){int tempa;ab;btemp;
}3、作为函数返回值来传递例如重载左移运算符需要输出多个内容就需要返回引用。
#include iostream
#include typeinfo
using namespace std;
#define sz(type) cout sizeof(type) endl;
int function1(int aa) // 以返回值的方法返回函数值
{return aa;
}
int function2(int aa) // 以引用方式返回函数值
{return aa;
}
int main()
{int a 10;// 第一种情况系统生成要返回值的副本即临时变量int b function1(a); // function1()的返回值先储存在一个a的副本中// 然后再把副本赋值给b// 第二种情况报错// function1(a) 20;// function1()的返回值为临时变量不能赋值即不能为左值// 第三种情况系统不会生成返回值的副本function2(a) 20; // OK 此时a的值变成了20coutaendl;
}重载左移运算符返回引用才会连续输出两个值
#include iostream
using namespace std;class Point
{
public:int x_, y_;Point(int x, int y) : x_(x), y_(y) {}friend ostream operator(ostream os, const Point p){os p.x_ p.y_ endl;return os;}
};int main()
{Point p(1, 2);coutpp;return 0;
}变量的作用域和生命周期
c的内存主要分为一下几个部分栈区、堆区、全局区静态区、文字常量区、程序代码区。
全局变量 存储在静态内存分配区整个程序的生命周期都可以使用其他文件使用关键字extern也可以使用 局部变量 存储在栈区与函数共存亡 全局静态变量 与全局变量类似也是存储在静态内存分配区生命周期与整个程序同在不过不能再其他文件使用。 局部静态变量 也是存储在静态内存分配区调用函数后便一直存在只不过只能在函数内可见。 类型别名与类型推断
1、别名typedef、using
2、推断auto、decltype
STL顺序容器
vector视作可变大小的数组可随机访问在非尾部的位置插入比较慢
deque双端队列支持随机访问在头尾位置插入和删除比较快
list双向链表支持双向顺序访问rbegin()、rend()在 list 任意位置插入和删除都比较快
forward_list单向链表只能单向顺序访问在 forward_list 的任意位置插入和删除都比较快
array固定大小的数组支持随机访问不能添加或者删除元素
string与 vector 类似专门保存字符串随机访问快在尾部插入和删除快
STL关联容器
map键值对一对一基于红黑树对关键字进行排序
set只保存关键字不重复
multimap关键字可以重复的 map 即一对多如统计数学课的学生成绩
multiset保存可以重复的关键字
unordered_map键值对一对一基于哈希值不对键值对进行排序
unordered_set只保存关键字不排序
unordered_multimap键值对一对多基于哈希值
unordered_multiset保存可以重复的关键字不排序
STL容器适配器
包括stack、queue、priority_queue
stack 和 queue 基于deque实现 priority_queue 基于 vector 实现
流对象
包括输入流对象ostream如std::cin从键盘读取数据输出流对象istream如std::cout向屏幕写入数据
还有文件输入流对象ifstream使用 std::ifstream 来创建对象将数据从文件中读取出来文件输出流对象ofstream使用 std::ofstream 来创建对象将数据写入文件
#include iostream
#include fstream
using namespace std;void test01()
{ofstream file;file.open(text.txt, ios::out);file xinm endl;file namji endl;file.close();
}
void test02()
{ifstream ifile;ifile.open(text.txt, ios::in);if(ifile.is_open()){char buf[1024];while(ifile buf){cout bufendl;}}ifile.close();
}int main()
{test02();return 0;
}使用二进制流读写文件
#include iostream
#include fstream
using namespace std;
class Person
{
public:// Person(char name[], int age):name_(name), age_(age){}char name_[20];int age_;
};void test01()
{ofstream file;file.open(text.txt, ios::out | ios::binary);Person p {hhhhh, 18};file.write((const char *)p, sizeof(p));file.close();
}
void test02()
{ifstream ifile;ifile.open(text.txt, ios::in | ios::binary);if (ifile.is_open()){// 1// char buf[1024];// while(ifile buf)// {// cout bufendl;// }// 2// char buf[1024];// while (ifile.getline(buf, sizeof(buf)))// {// cout buf endl;// }// 3// string buf;// while(getline(ifile, buf)){// cout buf endl;// }Person p;ifile.read((char *)p, sizeof(p));cout p.name_ p.age_ endl;}ifile.close();
}int main()
{test02();return 0;
}异常处理的构造和析构函数
若在 try 中抛出异常在转到 catch 前会对有关对象进行析构
#include iostreamusing namespace std;//异常处理的构造和析构函数
class Student{private:string name;int sno;public:Student(string name1,int sno1){namename1;snosno1;} ~Student(){coutDestruct Student:snoendl;}void checkSno(){if(sno0){throw sno;}else{coutname:snoendl; }}
};int main()
{try{Student a(pink,1);a.checkSno();Student b(floyd,0); //构造对象b.checkSno(); //抛出异常跳到catch语句块中}catch(int){couterror:sno0!endl;}return 0;
}可以看到上面这段代码的输出结果是先对a、b析构然后再转到catch输出内容。
类模板与继承
要注意继承的时候要加上基类的类型
#include iostreamusing namespace std;templateclass T
class Base
{public:T c;
};templateclass T
class Deri: public BaseT
{public:T a;
};int main()
{Deriint d;d.a4;d.c6;cout d.Base::cendl;// cout sizeof(Deriint)endl;return 0;
}继承时不能被继承的函数
包括构造函数、拷贝构造函数、析构函数注意operator函数是可以被继承的
#include iostream
#include cstring
using namespace std;class A{
public:A(){}A(int price, int weight):price_(price), weight_(weight){}A operator(const A a){cout operator1 endl;}
private:int price_;int weight_;
};class B: public A{
public:B(int price, int weight):price_(price), weight_(weight){}
private:int price_;int weight_;
};int main(){
// A a1(1,0);
// A a2;
// a2a1;B b1(10,0),b2(2,0);b2b1;return 0;
} 上面说明operator函数被继承下去了。
静态数据成员的只能在类外初始化
类内定义类外初始化一次然后在整个程序运行期间都可以存在
原因
1、静态成员变量存储在静态存储区域内在编译阶段就为他们分配内存空间
2、静态成员变量是类级别的他在所有类实例中是公有的如果允许在类内部初始化就可能导致每个实例都有一个独立的副本
3、这样可以避免多次初始化
#include iostream
#include cstdlib
#include ctime
#include vector
#include math.h
using namespace std;
class Point
{
public:Point(int x, int y) : x_(x), y_(y){}void setX(int val){x_ val;}void setY(int val){y_ val;}int getX() const{return x_;}int getY() const{return y_;}private:int x_;int y_;
};
class Circle
{
public:Circle(int x, int y, int r) : center_(x, y), r_(r){num_;cout Circle number: getNum() endl;;}static int getNum(){return num_;}friend double getDistance(const Circle c1, const Circle c2);private:static int num_;Point center_;int r_;
};int Circle::num_ 0;
double getDistance(const Circle c1, const Circle c2)
{double xdouble(c2.center_.getX()-c1.center_.getX());double ydouble(c2.center_.getY()-c1.center_.getY());return sqrt(x*x y*y);
}void testCircle()
{Circle c1(1, 2, 3);Circle c2(4, 6, 2);cout getDistance(c1, c2) endl;
}int main()
{testCircle();return 0;
}