NDK开发

NDK----C++篇(二)C++初始之特殊知识点

2021-06-16  本文已影响0人  初夏的雪

通过上一篇的学习,相信大家对C++有了初步的认识了,也聊了一些内容了,今天我们学点特殊的知识点,本文章的内容也比较简单。。。。

1、函数的可变参数

说明:

1、需要使用#include <stdarg.h> 来支持可变参数;

2、va_start 与 va_end函数成对出现,类似于文件操作(打开,关闭);

3、可变参数函数必须有一个指定的count ,用于遍历取值,防止越界;

实例代码如下:

/**
 * 可变参数的求和
 * @param count  指定可变参数的数量的参考值,用于在变量取出可变参数时越界,导致取出来的是系统的随机值
 * @param ...
 * @return
 */
int va_sum(int count, ...) {
    int sum = 0;
    va_list vp;
    //第一个参数是可变参考的开始动作,第二个参数是数量参考值
    va_start(vp, count);
    //遍历取值
    for (int i = 0; i < count; ++i) {
        int element = va_arg(vp, int);
        cout << "第" << i << "个元素的值是:" << element << endl;
        sum += element;
    }
    va_end(vp);
    return sum;
}

int main(){
    cout << "-------------可变参数学习-----------------" << endl;
    int sum = va_sum(5, 6, 2, 3, 4, 5);
    cout << "求和的结果是:" << sum << endl;
    return 0;
}

2、模板函数(相当于java的泛型)

说明:

       **格式:template <typename T , typename P>    T,P 就相当于定义的类型**

1、用于来解决因为参数类型不同,而功能相同需要重写很多函数的问题(代码复用)

2、使用方法:方法名<数据类型>(参数类型),数据类型也可以不写,会自动完成类型推导

3、编译期对模板函数会进行两次编译,a) 编译函数模板本身,进行语法检查等,b)对参数替换后的代码进行,其实及时普通函数的编译一样

4、模板函数针对使用的类型不同,会产生不同的函数(相当于编译器帮我们自己重载了该函数)

5、模板函数支持多个不同的类型参数:template <typename T,typename P,typename,Y>

6、可以使用<>空模板来限定编译器只能匹配模板函数,如果不限定会默认匹配普通函数

7、模板函数可以重载

实例代码如下:

template<typename T, typename P>
void fun(T t, P p) {
    cout << "模板函数:t=" << t << ",p=" << p << endl;
}
//模板函数重载
template<typename T>
void fun(T t) {
}

//下面的函数不是模板函数,只是一个普通的函数
void fun(int age, string name) {
    cout << "普通函数:age=" << age << ",name=" << name << endl;
}

int main(){
    fun<int, int>(1, 2);//指定模板类型(从左到右)
    fun("leon");//调用重载的模板函数
    fun<>("hello", "world");//限定默认匹配模板函数
    fun(88, "pig weight");//默认匹配普通函数
    return 0;
}

3、深浅拷贝

说明:

1、浅拷贝(值拷贝):将一个对象的值复制到另外一个对象中去,两个对象共享一份实体,这就是浅拷贝。

  **浅拷贝存在如下两个问题:**

   **1.1)浅拷贝存在同一个内存被释放多次的问题。**

   **1.2)两个指针指向同一个地址,当其中一个指针修改其内存的值时,会导致另外一个指针的值也随之改变。**

2、深拷贝(值与地址拷贝):另外开辟一个新的内存空间,将源内存中的值拷贝到新的内存空间,其实就是另个独立的内存,只不过他们的值是一样的而已,

3、自定义拷贝构造函数:如果有堆成员,必须采用深拷贝

实例代码如下:

class Pig {
public:
    char *name;

    Pig(const char *str)
            : name(new char[strlen(str) + 1]) {
        strcpy(name, str);
    }

    Pig(const Pig &s)
            : name(s.name) {}


    Pig &operator=(const Pig &s) {
        if (this != &s) {
            name = s.name;
        }
        return *this;
    }

    ~Pig() {
        if (name) {
//            delete[] name;
        }
        name = NULL;
    }
};

int main(){
    
    Pig blackPig("black");
    Pig redPig(blackPig);
    cout << "redPig的地址:" << redPig.name << ",------blackPig的地址:" << blackPig.name << endl;
    cout << "redPig=" << redPig.name << ", blackPig=" << blackPig.name << endl;
    
     (*redPig.name) = 'r';
    cout << "(*redPig.name)='r'修改后的redPig的地址:" << &redPig.name << ",-----blackPig的地址:" << &blackPig.name << endl;
    cout << "(*redPig.name)='r'修改后的值:redPig=" << redPig.name << ",-----blackPig=" << blackPig.name << endl;
    return 0;
}

4、四大类型转换

说明:

1、const_cast:将常量指针转化成非常量指针

  **原理:将常量指针指向的内存地址赋值给新的指针变量,所有修改的内存地址里面的值**

2、static_cast: (编译期)静态转化(看左边,左边是什么类型,后续操作就调用左边类型的成员)

  **指针相关的转化,父子类之间的转化都可以使用static_cast**

3、dynamic_cast:(运行期)动态转化

  **3.1)父类的函数必须为虚函数**

  **3.2)子类转父类可以,父类不能转子类**

  **3.3)多态转换的返回值,有则成功,null则转换失败**

4、reinterpret_cast 强制转换(笔者没有转换成功,编译报错)

  **4.1)静态转换可以做的 ,强制转换都可以**

  **4.2)用在任意指针(或引用)类型之间的转换;以及指针与足够大的整数类型之间的转换;从整数类型(包括枚举类型)到指针类型,无视大小**

实例代码:

class Person {
public:
    string name = "hello";
public:
    virtual void show() {
        cout << "Person show" << endl;
    }
};

class Worker : public Person {
public:
    void show() {
        cout << "Person show" << endl;
    }
};


int main(){

    //const_cast
    const Person *p1 = new Person();
    Person *p2 = const_cast<Person *>(p1);
    p2->name = "hello world";
    cout << p1->name << endl;
    
    
    //static_cast
    int n = 88;
    void *pVoid = &n;
    int *number = static_cast<int *>(pVoid);
    *number = 99;
    cout << *number << endl;

    Person * person1 = new Person();
    Worker* worker1=static_cast<Worker*>(person1);
    worker1->show();
    
     //dynamic_cast
    Person *person = new Worker();
    Worker *worker = dynamic_cast<Worker *>(person);
    if (worker) {
        cout << "转换成功" << endl;
    } else {
        cout << "转换失败" << endl;
    }
    
      //reinterpret_cast-----笔者没有测试成功  Cast from pointer to smaller type 'long' loses information
//    Person * person2 = new Person();
//    int playerValue = reinterpret_cast<int>(person2); // 把对象变成数值----

    return 0;
}

下节预告:C++的类

上一篇 下一篇

猜你喜欢

热点阅读