C++的模板类型强制转换问题,有偿

各位带佬,我写了一个模板类型,目的是支持一些常用类型的变量之间做类型转换。内容大概是这样的:

template<typename T>
class MyStyle
{
其他函数
public:
//模板类型转换
    template<typename C>
    operator Style(){
    内容}
//内置类型转换
    template<typename C>
    operator C(){
    内容
    }
//转换到自定义的Array上
    template>
    operator Array(){
    内容
    }
}

现在问题是:
这几个函数单独定义,就都可以实现,通过编译且运行没有问题;
如果三个函数同时定义,就会出现只有内置类型转换可能成功,其他转换的语句在编译时报c2440错误;
转换时使用的是static_cast,如

Style<int> a;
static_castdouble>>(a);
或者
static_cast<double>(a);
或者
static_castdouble>>(a);

希望有带佬指点一下,十分感谢


可以参考下这里

https://justinwei.blog.csdn.net/article/details/78677119

你的class定义时类名是MyStyle,声明变量时又是用的Style,你自己搞清楚你在做什么了吗?

#include <iostream>
using namespace std;

template<typename T>
class Style{

};

template<typename T>
class Array{

};

template<typename T>
class MyStyle
{
public:
//模板类型转换
    template<typename C>
    operator Style<C>(){
        cout<<"Style<C>"<<endl;
    }
//内置类型转换
    template<typename C>
    operator C(){
        cout<<"C"<<endl;
    }
//转换到自定义的Array上
    template<typename C>
    operator Array<C>(){
        cout<<"Array<C>"<<endl;
    }

};

int main()
{
    MyStyle<int> a;
    static_cast<int>(a);
    static_cast<Style<int>>(a);
    static_cast<Array<int>>(a);
    return 0;
}

c++学习笔记(六、模板和类型转换)

c++学习笔记(六、模板和类型转换)
现在进⼊了c++⾼级课程了,前⾯5节是c++的语法基础,从现在开始就是c++提⾼篇了。
模板是泛型编程的基础,泛型编程即以⼀种独⽴于任何特定类型的⽅式编写代码。
模板是创建泛型类或函数的蓝图或公式。库容器,⽐如迭代器和算法,都是泛型编程的例⼦,它们都使⽤了模板的概念。
第 1 页
6.1 函数模板
我们可以⽤函数模板来定义函数:
//模板技术,类型参数化,编写代码可以忽略类型。
template//这⼀个是函数模板的关键字,为了区别函数模板和普通函数
void MySwap(T &a, T &b){
T temp = a;
a = b;
b = temp;
第 2 页
}
//也可以吧class写成typename
template
void MySwap1(T &a, T &b){
T temp = a;
a = b;
b = temp;
}
//使⽤⽅法有两种:
int main(int argc,char**argv)
第 3 页
{
int a =10;
int b =11;
//1. ⾃动类型推导
printf("a b %d %d\n", a,b);
MySwap(a, b);
printf("a b %d %d\n", a,b);
MySwap1(a, b);
printf("a b %d %d\n", a,b);
//2.显⽰的指定类型
第 4 页
printf("a b %d %d\n", a,b);
MySwap(a, b);
printf("a b %d %d\n", a,b);
return0;
}
函数模板和普通函数在⼀起调⽤规则:

  1. 函数模板可以像普通函数那样可以被重载
  2. c++编译器优先考虑普通函数(如果普通函数满⾜的话)
    第 5 页
  3. 如果函数模板可以产⽣⼀个更好的匹配,那么选择模板
  4. 可以通过空模板实参列表的语法限定编译器只能通过模板匹配(不是很懂)
    函数模板和普通函数的区别:
  5. 函数模板不允许⾃动类型转化
  6. 普通函数能够⾃动类型转化
    强制调⽤模板 ⽤MySwap<>(a, b);
    第 6 页
    函数模板机制结论:
  7. 编译器并不是把函数模板处理成能够处理任何类型的函数
  8. 函数模板通过具体类型产⽣不同函数
  9. 编译器会对函数模板进⾏两次编译,在声明的地⽅对模板代码本⾝进⾏编译,在调⽤的地⽅对参数替换后的代码进⾏编译。
  10. 2 类模板
  11. 2.1 类模板
    第 7 页
    正如我们上⾯定义的函数模板⼀样,类也是有模板的,⽤法跟函数模板差不多:
    template
    class Stack {
    private:
    vector elems;// 元素
    public:
    void push(T const&);// ⼊栈
    void pop();// 出栈
    第 8 页
    T top()const;// 返回栈顶元素
    bool empty()const{// 如果为空则返回真。
    return elems.empty();
    }
    };
    参考菜鸟教程:
    我觉得菜鸟教程 举的例⼦很不错,实现了⼀个栈,栈的元素确实不确定,挺好的,我这⾥就不写了,写了也是抄过来。
    第 9 页
  12. 2.2 类模板和继承
    template
    class Animal
    {
    public:
    T m_age;
    private:
    };
    //有两种继承的⽅式
    //1.⼦类也是类模板
    第 10 页
    template
    class cat :public Animal
    {
    public:
    private:
    };
    //2.可以实例化的类,把实际类型替换掉T
    class cat1 :public Animal
    {
    第 11 页
    public:
    private:
    };
    //使⽤⽅法
    cat c;
  13. 2.3 类模板类外实现
    类模版在类内实现,这个⽐较简单,把例⼦发出来就可以了:
    第 12 页
    template
    class Animal
    {
    public:
    Animal(T age)
    {
    this->m_age = age;
    }
    void show(){
    printf("Animal %d\n", m_age);
    第 13 页
    }
    private:
    T m_age;
    };
    //有两种继承的⽅式
    //1.⼦类也是类模板
    template
    class cat :public Animal
    {
    public:
    第 14 页
    cat(): Animal(10)
    {}
    private:
    };
    类内部实现,可以直接使⽤,⽐较简单,但是c++⽀持多⽂件,所以有时候也需要在类外部实现。实现⼀个类模板类外实现:
    第 15 页
    //类的声明
    template
    class Animal
    {
    public:
    Animal(T age);
    void show();
    private:
    T m_age;
    };
    第 16 页
    template
    class cat :public Animal
    {
    public:
    cat();
    private:
    };
    //类的实现
    template//函数上⾯添加模板声明
    第 17 页
    Animal::Animal(T age){//类名后⾯也要加
    this->m_age = age;
    }
    template
    void Animal::show(){
    printf("Animal %d\n", m_age);
    }
    template
    cat::cat(): Animal(10)
    第 18 页
    {
    }
    当类外实现的时候遇上了友元函数,那就更难受了:
    templateclass Animal;
    template ostream&operator<<(ostream& os, Animal& a);
    template
    class Animal
    {
    第 19 页
    public:
    Animal(T age);
    void show();
    //重载<<;操作符
    friend ostream&operator<<(ostream& os, Animal& a);
    private:
    T m_age;
    };
    template
    第 20 页
    ostream&operator<<(ostream& os, Animal& a)
    {
    os << a.m_age <<"年龄"<< endl;
    return os;
    }
    第 21 页
    友元函数需要注意3个地⽅:
    第⼀个⾸先要声明
    第⼆个就是在类中声明的friend中需要在函数名后⾯加
    第三个就是实现的时候,要跟其他的函数⼀样,要加template 需要更注意⼀点,类外实现,少⽤友元函数
  14. 2.4 多⽂件类模板外实现
    想不到多⽂件实现这个类模板也这么难受
    第 22 页
    animal.h
    #pragma once
    #include
    templateclass Animal;
    templatevoid show_aa(Animal& a);
    template
    class Animal
    {
    public:
    第 23 页
    Animal(T age);
    void show();
    //重载<<;操作符
    friend void show_aa(Animal& a);
    private:
    T m_age;
    };
    //有两种继承的⽅式
    //1.⼦类也是类模板
    第 24 页
    template
    class cat :public Animal
    {
    public:
    cat();
    private:
    };
    animal.cpp
    第 25 页
    #include"animal.h"
    template
    Animal::Animal(T age){
    this->m_age = age;
    }
    template
    void Animal::show(){
    printf("Animal %d\n", m_age);
    }
    template
    第 26 页
    cat::cat(): Animal(10)
    {
    }
    template
    void show_aa(Animal& a)
    {
    printf("gjah %d\n", a->m_age);
    }
    main.c
    int main(int argc,char**argv)
    第 27 页
    {
    //cat c;
    //c.show();
    //cout << c;
    return0;
    }
    如果把main.c中申请的对象屏蔽掉,就不会出现错误,如果打开,会出现以下错误:

第 28 页
这个跟类模板两次编译有关,因为是多⽂件的时候,是每个⽂件⾃⼰单独编译成.o⽂件,然后在链接器链接每个.o,才会⽣成可执⾏⽂件。
问题就出在编译成.o的时候,因为animal.cpp是⼀个函数模板,这时候编译的话,是属于第⼀次编译,只是检查函数模板是否有语法问题,结果这个cpp没有语法没问题,所以编译通过,⽣成.o⽂件,接下来main.c这个直接调⽤了模板函数,但是这个⽂件也没有声明,
第 29 页
所以main.c中会标注⼀些符号,代表着这个需要到链接的时候由链接器寻找,所以也没有问题,编译通过。
这时候到链接器,链接器就拿到main.c中的cat::cat(),去各个.o中寻找有没没对应的函数,这时候animal.o中只有原来的函数模板,没有具体编译成函数,因为函数模板是需要两次编译的,⼀次是调⽤的时候,所以这时就没有找到对应的函数,所以链接的时候报错。
有解决⽅法,就是把包含的头⽂件
第 30 页
修改成cpp⽂件即可编译完成,这时候main.cpp中就有函数模板的声明和调⽤了,就可以完成⼆次编译了。
但是正是的⼯程中,不会这么使⽤的,⽽是把函数模板的声明和实现写在⼀个⽂件中,这个⽂件的后缀就是hpp.
怪不得当初不知道hpp是什么意思,现在终于知道了。
6.2.5 类模板碰到static成员
第 31 页
template
class Animal
{
public:
Animal(T age);
void show();
//重载<<;操作符
friend void show_aa(Animal& a);
static int aa;
第 32 页
private:
T m_age;
};
templateint Animal::aa =0;
类模板中初始化静态变量跟也差不多,但是有⼀个问题是这个共享的变量aa,是跟那些类共享的。
其实我们类模板是⼀个具体类的⼀个模板,到具体使⽤的时候,还是需要定义⼀个具体类,这个具体类
第 33 页
是不⼀样的,⽐如上⾯的类模板,我们可以定义Animal, Animal,这两种不同的类,当然还有其他的,这⾥就举两个例⼦,这两个类都是具体的类,所以静态变量aa,是Animal这个家族类共有⼀个,Animal这个家族类也共有⼀个。
T&& 是对右值取引⽤。
6.3 类型转换
说到类型转换,c语⾔的类型转换是强制的,也最简单(type)变量,这
第 34 页
样就可以强制转换。这样⼦存在很⼤的问题,不明显,并且没有类型检查,直接可以转,c++为了克服这些缺点,引进了4个新的类型转换操作符。
c++提供了四种类型转换,分别适⽤于其他场景static_cast用于内置的数据类型转换。 (具体也不清楚)
dynamic_cast子类和父类之间的多态类型转换。(转换之前做类型检查)
第35页 Bai du 文库
const_cast添加或去掉const属性转换
reinterpreter_cast强制类型转换。(想怎么转就怎么转)
用法也简单:
类型转换操作符<目标类型>变量一般情况下,不建议做类型转换。

https://m.baidu.com/from=1020761t/bd_page_type=1/ssid=0/uid=0/pu=usm%401%2Csz%40320_1001%2Cta%40iphone_2_11.0_19_11.7/baiduid=F16DE8FE16DFAE2235E549EEC8D00337/w=0_10_/t=iphone/l=1/tc?ref=www_iphone&lid=11756220317542709824&order=1&gsflag=0&fm=alop&isAtom=1&waplogo=1&clk_info=%7B%22tplname%22%3A%22www_normal%22%2C%22srcid%22%3A1599%2C%22jumpType%22%3A%22%22%7D&is_baidu=0&tj=www_normal_1_0_10_title&vit=osres&cltj=normal_title&asres=1&nt=wnor&title=C%2B%2B%E4%B8%AD%E5%9B%9B%E7%A7%8D%E5%BC%BA%E5%88%B6%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2%E9%97%AE%E9%A2%98_Littlehero_121%E7%9A%84%E5%8D%9A%E5%AE%A2-CSDN%E5%8D%9A%E5%AE%A2&wd=&eqid=a3267c17785cfa4010000005630842d3&w_qd=IlPT2AEptyoA_yiWZ9kasQSuB5RVn8sp659YmwLVveErRRgvNj6dvZPjdP-7cc3&bdver=2&tcplug=1&dict=-1&sec=23523&di=490c4507442c128f&bdenc=1&tch=124.224.300.205.1.17&nsrc=k4638UOP4j5EzwRkgkRcer8C7zy%2FWPGw%2FNBWj7bP4YhuQRTRRz3JqR2%2BvdJFSWGlertjPQkKokzUiRRsWdWhcwKzSwMjXznGc7UoGchNmf3KB%2B553y2PMKtNE%2BH5Q6HuajUFyXPXIc19C1CJSDkahQ%3D%3D

https://m.baidu.com/from=1020761t/bd_page_type=1/ssid=0/uid=0/pu=usm%401%2Csz%40320_1001%2Cta%40iphone_2_11.0_19_11.7/baiduid=F16DE8FE16DFAE2235E549EEC8D00337/w=0_10_/t=iphone/l=1/tc?ref=www_iphone&lid=11756220317542709824&order=4&gsflag=0&fm=alop&isAtom=1&waplogo=1&clk_info=%7B%22tplname%22%3A%22www_normal%22%2C%22srcid%22%3A1599%2C%22jumpType%22%3A%22%22%7D&is_baidu=0&tj=www_normal_4_0_10_title&vit=osres&cltj=normal_title&asres=1&title=C%2B%2B%E5%BC%BA%E5%88%B6%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2%E7%9A%84%E5%9B%9B%E7%A7%8D%E6%96%B9%E5%BC%8F_C%E8%AF%AD%E8%A8%80_%E8%84%9A%E6%9C%AC%E4%B9%8B%E5%AE%B6&wd=&eqid=a3267c17785cfa4010000005630842d3&w_qd=IlPT2AEptyoA_yiWZ9kasQSuB5RVn8sp659YmwLVveErRRgvNj6dvZPjdP-7cc3&bdver=2&tcplug=1&dict=-1&sec=23523&di=647513628ef0958c&bdenc=1&tch=124.267.78.1386.2.887&nsrc=o34BjaVBU0LDE8gL0XDj303j%2FwlA1LMoKNovf8AdMIfaAa3IE6NFuHvzGPTo%2BRckno3Ip352XXADKlsk7OAhDDcbA8sE99VUjgfFIpctmp4%3D

修改方案:
点击“项目 ” --> “属性” --> "语音" --> ”复合模式“,将”复合模式“改成 否(/permissive)