• Geek_077da0
    2019-12-23
    老师您好,看到这一讲想问一个一直想问的问题。我是一个在校学生,目前学完了c++的基本语法知识并且看了一些相关的书籍,但平时能自己动手写代码的机会只有刷leetcode的时候,想请问一下老师,在去公司实习之前,有没有什么项目适合初学者练练手的。不然感觉自己看了这么多理论终究只是在纸上谈兵。

    作者回复: 可以尝试把平时用 Python、Bash 写的小工具改成用 C++。使用现代 C++,这种处理也不会太麻烦。

    还有就是小的网络应用、数据处理应用等等。Leetcode 是考算法的,对语言技巧是没啥帮助。

    
     4
  • panda
    2020-01-05
    第一题通过查阅资料,c++的多态性分专用多态和通用多态,专用多态又分重载多态和强制多态,通用多态又分包含多态和参数多态。
    重载多态:函数重载和操作符重载。
    强制多态:使一个变量类型加以变化让其符合函数操作的要求。
    如:double a = 1.0;
           int b = 2;
           double c = a + b;
    此时b会强制转换成double再进行+操作。
    包含多态:虚函数重构。
    参数多态:课程里的函数模板。
    第二题,对各语言了解太浅,需老师给出解答。
    展开

    作者回复: 思考题有些是没有固定答案的,就是希望大家去思考一下。多态的分类也有很多种。包含多态、参数多态和重载多态都是常见的提法,但强制多态这个说法我不熟,查了一下才确定有这种说法,感觉和一般的多态这个词的理解还是有点差异的……

    就这第二题而言,也是希望大家去比较学习过的其他语言。这基本上取决于语言本身在类型方面的特性。

    以 Python 为例,它是动态类型的语言。所以它不会有真正的静态多态。但和静态类型的面向对象语言(如 Java)不同,它的运行期多态不需要继承。没有参数化多态初看是个缺陷,但由于 Python 的动态参数系统允许默认参数和可变参数,并没有什么参数化多态能做得到而 Python 做不到的事。

    
     2
  • Encoded Star
    2020-01-03
    1.C++ 支持2种吧, 静态多态和动态多态,静态多态它在编译器,通过函数重载,用算符重载的方式被调用者使用,动态多态也叫运行时多态,它可以通过虚函数和继承来实现,实现是,编译器会将进程运行过程中动态绑定
    2.支持多态的语言一般是面向对象的语言,所以并非所有的都有。

    作者回复: 还不够全面。可以读读参考资料。

     1
     1
  • Jason
    2020-01-16
    老师,在c++的多态中,有没有一种方式可以通过基类的指针获取实际子类的类型呢?比如我定义的两个protobuf的类型里都有user_id的字段,在代码中为了通用(不想每个类型写一个函数),反射出来传递给外围都是pb的基类指针,因为要设置子类的成员就必须要强制类型转换,但是这种情况下又拿不到子类的实际类型去做转换。decltype(基类)得到的还是基类类型

    作者回复: decltype 得到的是编译期的类型。你需要的是运行期的类型,C++ 里挺有争议(跟异常类似)的功能——RTTI。(还是要强调一句,你应该考虑是否用虚函数可以达到你需要的功能。很多项目,如 Google 的,会禁用 RTTI。)

    你可以用 dynamic_cast 来转换成你需要的指针类型,如果类型不对,会得到空指针。你也可以用 typeid 直接来获取对象的实际类型。下面的代码演示一下(需要 Boost;没有安装 Boost 请自行调整,也只是不能输出友好类名而已):

    #include <iostream>
    #include <typeinfo>
    #include <boost/core/demangle.hpp>

    using namespace std;
    using boost::core::demangle;

    class shape {
    public:
      virtual ~shape() {}
    };

    class circle : public shape {
    };

    int main()
    {
      shape* ptr = new circle();
      auto& type = typeid(*ptr);
      cout << type.name() << endl;
      cout << demangle(type.name()) << endl;
      cout << boolalpha;
      cout << (type == typeid(shape) ? "is shape\n" : "");
      cout << (type == typeid(circle) ? "is circle\n" : "");
      delete ptr;
    }

    在 GCC 下的输出:

    6circle
    circle
    is circle

    
    
  • Jason
    2020-01-14
    老师,在参考资料3中,针对模板重载解析的例子
    //
    template <class T> // //(a)与
    void f(T)之前相同的旧基础模板 ;

    template <> // //(c)显式专业化,这一次(a)
    void f <>(int *);

    template <class T> // //(b)第二个基本模板,重载(a)
    void f(T *);

    // ...

    int * p;
    f(p);

    是否针对int*的全特化在(a)的后面,就是属于(a)的基础模板的全特化,在(b)后面就是(b)的全特化。所以int*全特化放置的位置不同,导致了模板裁决时,因为选取了不同的基础模板而导致了不同的结果。是这样吗?
    展开

    作者回复: 是的,这是个大坑,所以Herb建议对函数用重载就行了,不会有惊讶的行为。

    
    
  • 范闲
    2020-01-10
    多态:
    类的话是基于虚继承衍生出来的
    函数的话是基于函数重载衍生出来的


    不支持所有的多态方式:应该和语言的设计理念和哲学相关。
    展开

    作者回复: 可以看看其他的一些读者评论。

    
    
  • 花晨少年
    2019-12-29
    参数满足随机访问迭代器的要求。
    ———
    是因为sort 是个复合排序,主体是使用 快速排序,而快排貌似是有随机访问的需求吗

    作者回复: sort不一定是快速排序,但通用的高性能排序算法一般都要求随机访问。sort解决的是通用情况。list::sort 则解决一种不能随机访问的特殊情况。

    
    
  • lyfei
    2019-12-24
    老师您好,就是我对容器共性这一块有点疑惑:
    比如老师讲的容器中的共性:begin, end等,但是又提到" C++ 的标准容器没有对象继承关系";那对于不同的容器来说,vector, map, list等都得各自去实现自己的begin, end方法吗?
    那既然不同的容器有着诸多的共性,为什么C++里不用继承呢?
    谢谢老师的回复

    作者回复: 想一想:

    为什么要继承?继承的话,能带来什么好处?

     2
    
  • Scott
    2019-12-24
    请问前几讲中最后的问题的答案可以公布一下吗?

    作者回复: 具体一点吧。哪一题你特别想知道又没有正确的回答?😎

    
    
  • 总统老唐
    2019-12-24
    吴老师,学完这一课,有 3 点疑问:
    1,你提到的方法一,“添加代码,让那个类型支持所需要的操作(对成员函数无效)”,这里说“对成员函数无效”是具体指的什么情况?
    2,实现static_assert功能时,定义 struct 模板如下: template<bool> struct compile_time_error, 和常见的模板定义头部 template <typename T> 的格式看起来不一样,常见的这种格式中参数类型是未定的,但是compile_time_error这个模板,参数明确指定是 bool 型,这是模板的另一种形式么?
    3,我尝试做了以下实验
    template <typename T>
    T addData(T a, T b)
    {
        return a + b;
    }

    double addData(double a, double b)
    {
        return (int)a + (int)b;
    }

    template <>
    double addData(double a, double b)
    {
        return (int)a + (int)b;
    }
    当我调用 addData(1.5, 2.5)时,发现调用的是针对double的重载函数,而不是模板针对double 的特化,这是为什么?
    展开

    作者回复: 1. 一般而言,不应该去修改别人的类。容易出问题。所以不能添加成员函数。

    2. 模板参数可以是类型,也可以是常数表达式,包括整数类型常数、枚举、指针、引用。

    3. 重载比特化优先。一般而言,函数特化是不推荐的。具体看参考资料 3。

    
    
  • tt
    2019-12-23
    从来没有把C++的模板编程和鸭子类型联系到一起,以前一提到鸭子类型,就想到了PYTHON和JAVASCRIPT。现在想想,按照鸭子类型的定义,那么JAVA也是支持它的。

    一直感觉C++的模板编程就是一个静态实现的“动态类型子语言”:完全可以像写JAVASCRIPT一样写C++代码,只是需要先编译一下再运行。也许JAVASCRIPT的实现比如V8引擎应该大量使用它吧。

    但最后的总结,静态多态主要是用于算法复用。好像上面的想法又不太行的通了。不过,如果把类型的行为也看作一种算法的话,似乎又是一个解决办法。

    没看过V8这么复杂的源码,也许有一天去看看吧。
    展开

    作者回复: 静态语言的鸭子类型和动态语言还是有区别的。毕竟静态语言,如 C++,需要在编译时绑定所有的符号,否则就会出错……下面还会有例子,和 C++ 如何试图解决、改善这些问题的。编译期行为要讲上很多讲的。

    
    
我们在线,来聊聊吧