• C/C++ 答疑解问


    1. sizeof(string)的大小

    string属于类,类的大小就是类中成员变量(非静态)加上指向虚函数表的指针以及指向虚基类表的指针加起来的和。因为string是一个模板类,受具体的实现来决定其sizeof。实际上,到了C++中,对类的sizeof往往没有意义。这涉及到编译器在实现类对象时采用的数据结构。

    VC6.0:sizeof(string) = 16;
    VS2010:sizeof(string) = 32;

    可以发现std::string在VC6.0和VS2010里面的实现并不相同。


     2. new、delete与malloc、free的关系

    malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
    对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
    因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。

    参考:malloc/free和new/delete的区别


     3. 泛化、关联、组合、聚合以及依赖的区别

    依赖:用到了别人的方法或变量;关联:对称的,好比你是我的朋友,我也是你的朋友;聚合:非对称的,员工与公司就是聚合关系,还有一个重要特点就是生命周期可以不同,员工离开了公司还是可以活的;组合:生命周期一致,好比人与心脏,一个没了另一个也没了。强度:依赖<关联<聚合<组合。

    详见:关联、组合、聚合、依赖关系比较


     4. 分别写出BOOL,int,float,指针类型的变量与“零”的比较语句。

    BOOL: if (flag) or if (!flag)
    int:    if (n == 0) or if(n != 0)
    float:   const float EPSINON = 0.00001;
         if ((x >= - EPSINON) && (x <= EPSINON))
         其中EPSINON 是允许的误差(即精度),在允许误差内的就认为是相等的
    pointer: if (p == NULL) or if(p != NULL)

    参见:零值比较--BOOL,int,float,指针变量与零值比较的if语句


    5. (1)如何打印出当前源文件的文件名以及源文件的当前行号?

    cout << __FILE__;
    cout << __LINE__;

    __FILE__和__LINE__是系统预定义宏,这种宏并不是在某个文件中定义的,而是由编译器定义的。

      (2)如何判断一段程序是由C 编译程序还是由C++编译程序编译的?

    #ifdef __cplusplus//两个下划线
    cout<<"c++";
    #else
    cout<<"c";
    #endif
    

    6. 在C++程序中调用被C编译器编译后的函数,为什么要加extern “C”?  

    详见:C++中extern “C”含义深层探索


    7. 写出Windows消息机制的流程。

    (1)操作系统接收到应用程序的窗口消息,将消息投递到该应用程序的消息队列中。
    (2)应用程序在消息循环中调用GetMessage函数从消息队列中取出一条条的消息。取出后,以对消息进行一些预处理,如放弃对某些消息的响应,或者调用TranslateMessage产生新的消息。
    (3)应用程序调用DispatchMessage,将消息回传给操作系统。
    (4)系统利用窗口过程函数调用窗口过程,对消息进行处理。

    通常我们编写的消息循环代码如下:

    while(GetMessage (&msg, NULL, 0, 0))
    {
        TranslateMessage (&msg) ;
        DispatchMessage (&msg) ;
    }

    TranslateMessage函数将虚拟键消息转换为字符消息。DispatchMessage实际上是将消息回传给操作系统,由操作系统调用窗口过程函数对消息进行处理。
    从消息队列中获取消息还可以调用PeekMessage函数,发送消息可以使用SendMessage和PostMessage函数。


    8. 引用与指针有什么区别?

    (1)引用必须被初始化,指针不必。
    (2)引用初始化以后不能被改变,指针可以改变所指的对象。
    (3)不存在指向空值的引用,但是存在指向空值的指针。
    (4)从内存上来讲,系统为指针分配内存空间,而引用与绑定的对象共享内存空间,系统不为引用变量分配内存空间。所以引用访问对象是直接访问,指针访问对象是间接访问。


    9. 网络相关知识

    集线器Hub工作在OSI参考模型的(物理)层;交换机Switch工作在OSI参考模型的(数据链路)层;路由器Router工作在OSI参考模型的(网络)层;

    IP地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与之后才能区分哪些是网络位哪些是主机位。

    ARP(Address Resolution Protocol)地址解析协议将IP地址转化为主机物理地址(MAC地址),对应RARP协议。

    ICMP:Internet Control Message Protocol(网际控制报文协议)的缩写。它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。
    ICMP的一个重要应用就是分组网间探测PING(Packet InterNet Groper),用来测试两个主机之间的连通性。
    另一个非常有用的应用是traceroute(UNIX系统中名字,Windows对应的命令是tracert),它用来跟踪一个分组从源点到终点的路径。

    DHCP:(Dynamic Host Configuration Protocol)动态主机配置协议,是一种让系统得以连接到网络上,并获取所需要的配置参数手段。这种机制允许一台计算机加入新的网络和获取IP地址而不用手工参与。


     10. (1) 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)。

    #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL

    在C语言中,宏是产生内嵌代码的唯一方法。对于嵌入式系统而言,为了能达到性能要求,宏是一种很好的代替函数的方法。
    注意几点:
    1). #define 语法的基本知识(例如:不能以分号结束,最好将宏定义中的“参数”和整个宏用用括号括起来),函数宏被调用时只是进行简单的字符替换,而不是“值传递”。
    2). 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
    3). 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
    4). 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。

    (2) 写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。

    #define MIN(A,B) ((A)<=(B) ? (A):(B))

    而比如代码:least = MIN(*p++, b); 将被替换为:((*p++)<=(b) ? (*p++):(b)),发生的事情无法预料,因而不要给宏定义传入有副作用的"参数"。


    11. const 和 #define的区别

    (1) 编译器处理方式不同:define宏是在预处理阶段展开;const常量是编译运行阶段使用。
    (2) 类型和安全检查不同:define宏没有类型,不做任何类型检查,仅仅是字符替换,并且在字符替换可能会产生意料不到的错误(边际效应);const常量有具体的类型,在编译阶段会执行类型检查。有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。
    (3) 存储方式不同:define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存;const常量会在内存中分配(可以是堆中也可以是栈中)

    在C++ 程序中只使用const常量而不使用宏常量,即const常量完全取代宏常量。


    12. 设计模式:工厂模式和单例模式介绍一下?

    单体模式 很简单,就是将构造函数变为私有,那么就不能通过new来创建对象。同时创建一个共有的静态的方法来获得实例,代码如下:C++

    //Singleton.h
    class Singleton  
    {
    public:
    	static Singleton* GetInstance();
    private:
    	Singleton() {}
    	static Singleton *singleton;
    };
    //Singleton.cpp
    Singleton* Singleton::singleton = NULL;
    Singleton* Singleton::GetInstance()
    {
    	if(singleton == NULL)
    		singleton = new Singleton();
    	return singleton;
    }

    工厂模式有三个参与者,抽象产品(Product)、工厂(Creator)和具体产品(ConcreteProduct)。客户只会看到工厂和抽象产品。

    public interface Product{ 
        public String getName(); 
    } 
    
    public class ConcreteProduct implements Product{ 
        public String getName(){ 
            return "产品1"; 
        } 
    } 
    
    public class Creator{ 
        public static Product create1(){ 
            return new ConcreteProduct(); 
        } 
    }
    

    工厂模式的作用在于将创建具体产品的方法由工厂类控制,客户只需要知道产品的抽象类型。比如具体产品可以是:香蕉、苹果、橘子等,只需要通知一声工厂,工厂就会调用相应的 生产香蕉、生产苹果、生产橘子等函数,而客户不需要知道生产这些水果的具体过程,坐着等吃就行。

  • 相关阅读:
    第二次团队作业
    第一次团队作业
    软件工程结对编程第二次作业
    第四次软件工程作业
    Hadoop综合大作业
    hive基本操作与应用
    熟悉HBase基本操作
    爬虫大作业(爬取广州番禺职业技术学院新闻发布方)
    熟悉常用的HDFS操作
    数据结构化与保存
  • 原文地址:https://www.cnblogs.com/li-chong/p/3261527.html
Copyright © 2020-2023  润新知