C++学习笔记(二)-- 兼谈对象模型

本文介绍了C++中的重要编程概念,包括转换函数、非显式单参数构造函数及其可能导致的二义性,以及如何使用显式构造函数避免问题。此外,讨论了类模板、函数模板、模版特化、智能指针如`share_ptr`,以及C++11引入的新特性如范围基础for循环、auto关键字和变长模板。还涉及了动态绑定、内存管理和自定义`new`、`delete`操作符。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        oprator type() const;

        explicit complex(...): initialization list {  }

        pointer-like object

        function-like object

        Namespace

        template specialization

        Standard Library

since C++11:

        variadic template

        move ctor

        Rvalue reference

        auto

        lambda

        range-base for loop

        unordered containers

......

conversion function, 转换函数 ---------1⃣️

        operator 类型 () const {...}

//e.g fraction类--一个double型小数
class Fraction{
public:
    //功能:将其他类型转换成该类型
    Fraction(int num, int den = 1): m_numerator(num), m_denominator(den) { }


    //conversion function, 转换函数
    //功能:让该类可以作为小数使用,没有return type,没有参数传入,const修饰函数
    operator double() const {
        return (double) (m_numerator / m_denominator);
    }


private:
    int m_numerator;//分子
    int m_denominator;//分母
}


//test
Fraction f(3, 5);
double d = 4 + f; //调用operator double()将f转换为0.6

 non-explict-one-argument constructor,不清晰的单参数构造函数 ----------2⃣️

class Fraction{
public:
    //non-explict-one-argument constructor,不清晰的单参数构造函数
    //功能:将其他类型转换成该类型
    Fraction(int num, int den = 1): m_numerator(num), m_denominator(den) { }


    //函数重载“+”:左值为本身,右值为传入参数
    Fraction operator+(const Fraction& f){
        return Fraction(...);
    }

private:
    int m_numerator;
    int m_denominator;
};

//test
Fraction f(3,5);
Fraction d2 = f + 4; //调用non-explict-one-argument ctor
                     //再调用operator+

若1⃣️和2⃣️并存,可能会有二义性/多条路径(函数)实现 -- error

explict-one-argument constructor,明确的单参数构造函数

class Fraction{
public:
    //explict-one-argument constructor,明确的单参数构造函数
    explicit Fraction(int num, int den = 1): m_numerator(num), m_denominator(den) { }

    operator double() const {
        return (double) (m_numerator / m_denominator);
    }

    Fraction operator+(const Fraction& f){
        return Fraction(...);
    }

private:
    int m_numerator;
    int m_denominator;
};

//test
Fraction f(3,5);
Fraction d2 = f + 4; //Error:conversion from 'double' to 'Fraction' requested

pointer-like classes,关于智能指针 

template<class T>
class share_ptr{
public:
    T& operator*() const{
        return *px;
    }
    
    T* operator->() const{
        return px;
    }

    share_ptr(T* p) : px(p) { }

private:
    T* px;
    long* pn;
...
};

        “->”重载后还是会继续使用

pointer-like classes, 关于迭代器

 

reference oprator*() const{
    return (*node).data;
}

pointer operator->() const{
    return &(operator*());
}

//***************************⬇️

list<Foo>::iterator ite;
...
*ite; //获得一个 Foo object
ite->method();
    //意思是调用 Foo::method()
    //相当于(*ite).method();
    //相当于(&(*ite))->method();

namespace

using namespace std;
//----------------------
namespace jj01{
...
}

namespace jj02{
...
}

//test
int main(int argc, char** argv){
    jj01::test_member_template();
    jj02::test_member_template_param();
}

class template,  类模版

function template,  函数模版

        调用会进行实参推导,能推出类型,所以在调用时不需要制定类型

member template,  成员模版

template <class T1, class T2>//template class
struct pair{
    typedef T1 first_type;
    typedef T2 second_type;

    T1 first;
    T2 second;

    pair()
        :first(T1()), second(T2()) { }
    pair(const T1& a, const T2& b)
        :first(a), sencond(b) { }

    template <class U1, class U2>//template member
    pair(const pair<U1, U2>& p):
        first(p.first), second(p.sencond) { }
//很多成员模版会出现在类模版的构造函数中
};

specialization, 模版特化

        泛化   <---betray--->  特化

        full specialization & partial specialization

//泛化
template <class key>
struct hash {  };


//特化
template<>
struct hash<char> {
    size_t operator()(char x)const { return x; }
};

template<>
struct hash<int> {
    size_t operator()(int x)const { return x; }
};

template<>
struct hash<long> {
    size_t operator()(long x)const { return x; }
};

partial specialization, 模版偏特化 -- 个数上的偏

partial specialization, 模版偏特化 -- 范围上的偏

template template parameter, 模版模版参数

//template template parameter -- Container
template<typename T, 
                    template <typename T> 
                    class Container//容器
         >
class XCls{
private:
    Container<T> c;
public:
    ...
};

template<typename T>
using Lst = list<T, allocator<T>>;

//test
XCls<string, list> mylst1; //error:list容器有第二、第三默认值?
XCls<string, Lst> mylst2; //right
//template template parameter -- smartPtr
template<typename T, 
                    template <typename T> 
                    class SmartPtr//智能指针
         >
class XCls{
private:
    SmartPtr<T> sp;
public:
    XCls() : sp(new T) { }
};


//test
XCls<string, share_ptr> p1; //right
XCls<double, unique_ptr> p2; //error
XCls<int, weak_ptr> p3; //error
XCls<long, auto_ptr> p4; //right

C++标准库

        仿函数Functors;算法Algorithm;迭代器Iterators;容器Containers

1.variadic templates -- 数量不定的模版参数

void print(){
}

template <typename T, typename... Types>
void print(const T& firstArg, const Types&... args){
    cout << firstArg << endl;
    print(args...);//递归:拆成一个和一包
}

//test
print(7.5, "hello", bitset<16>(377), 42);//最后42时传入的是一个和0个
//调用42结束之后就会调用第一个空函数printf()

...就是一个所谓的pack(包)

        用于template parameters,就是 template parameters park(模版参数包);

        用于function parameter types,就是 function parameter types park(函数参数类型包);

        用于function parameters,就是 function parameters park(函数参数包)

2.auto(C++11)

        auto被定义为自动推断变量的类型

list<string> c;
...
list<string>::iterator ite;//ite的title-->可以用auto代替
ite = find(c.begin(), c.end(), target);

***

list<string> c;//创建一个容器
...
auto ite = find(c.begin(), c.end(), target);

***

//error: auto时要初始化
list<string> c;
...
auto ite;//error
ite = find(c.begin(), c.end(), target);

3.ranged-base for (since C++11)

//decl--定义/声明一个变量; Coll--容器
for( decl : coll ) {
    statement
}

//example:
// {2, 3, 5, 7, 9, 13, 17, 19} -- 自然而然声明的容器
for(int i : {2, 3, 5, 7, 9, 13, 17, 19} ) {
    cout << i << endl;
}


vector<double> vec;
...
//auto 可以去 “猜” elem的类型
//pass by value
for( auto elem : vec ) {
    cout << elem << endl;
}
//pass by reference
for( auto& elem : vec ) {
    elem *= 3; //改变值需要用reference
}

reference

        sizeof(reference) = sizeof(x)  --  object和其reference的大小相同,地址也相同

reference的常见用途

        reference通常不用于声明变量,而用于参数类型parameters type和返回类型return type的描述

//以下被视为same signature
//二者不能同时存在
double imag(const double& im) {...}
double imag(const double im) {...}//ambiguity

        const是函数的一部分,若两个相同函数一个有const一个没有 是可以共存的

关于vptr虚指针 和 vtbl虚表

        类内有虚函数时,有指针(4个字节)

        通过指针调用虚函数时,是动态绑定dynamic binding -- 虚机制

        动态绑定 :    1.通过指针;2.指针向上转型动作;3.调用的是虚函数

关于new, delete

        array new 一定要搭配 array delete

        重载     内存池设计 

::operator new, ::operator delete, ::operator new[], ::operator delete[]

void* myAlloc(size_t size){
    return malloc(size);
}

void myFree(void* ptr){
    return free(ptr);
}

//它们不可以被声明在一个namespace内
inline void* operator new(size_t size){
    cout << "jjhou global new()   \n";
    return myAlloc(size);
}
inline void* operator new[](size_t size){
    cout << "jjhou global new[]()   \n";
    return myAlloc(size);
}
inline void* operator delete(void* ptr){
    cout << "jjhou global delete()   \n";
    myFree(ptr);
}
inline void* operator delete[](void* ptr){
    cout << "jjhou global delete[]()   \n";
    myFree(ptr);
}

const

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值