现在的位置: 首页 > 综合 > 正文

C++零碎笔记二

2012年07月19日 ⁄ 综合 ⁄ 共 4502字 ⁄ 字号 评论关闭

这些都是06年时候在学校的时候写的,当时放在CSDN的blog上面,现整理一下搬过来。

1,赋值兼容性原则

一个公有派生类的对象在使用上可以被当作基类的对象,反之则禁止。具体表现在:
派生类的对象可以被赋值给基类对象。
派生类的对象可以初始化基类的引用。
指向基类的指针也可以指向派生类。

 

2,静态联编与动态联编

静态联编与动态联编
联编:
    程序自身彼此关联的过程,确定程序中的操作调用与执行该操作的代码间的关系。
静态联编(静态束定)
    联编工作出现在编译阶段,用对象名或者类名来限定要调用的函数。
动态联编
    联编工作在程序运行时执行,在程序运行时才确定将要调用的函数。

虚函数:
    虚函数是动态联编的基础。
1, 是非静态的成员函数。
2, 在类的声明中,在函数原型之前写virtual。
3, virtual 只用来说明类声明中的原型,不能用在函数实现时。
4, 具有继承性,基类中声明了虚函数,派生类中无论是否说明,同原型函数都自动为虚函数。
5, 本质:不是重载声明而是覆盖。(因为其不属于函数签名部分)
6, 调用方式:通过基类指针或引用,执行时会 根据指针指向的对象的类,决定调用哪个函数。

虚析构函数:   
    为了保正析构函数能够被正确的调用,因此析构函数一般都被声明为虚函数(除非此类不会被继承),我们称其为虚析构函数。
如:
class Base
{
public:
       virtual ~Base() { cout << "Base Destructor\n"; }
};

class Derived
{
public:
        virtual ~Derived() { cout << "Derived Destructor\n"; }
};

int main()
{
       Base *b = new Derived();
       delete b;
}

output:
    Derived Destructor
    Base Destructor

我以前好像做过这样的笔记,现在却不是很清楚了,呵呵。笔记如下:
       用多态性处理动态分配的类层次结构中的对象时存在一个问题。
如果delete运算符用于指向派生类对象的基类指针,而程序中又显示地调用该运算符删除每一个对象,
那么,不管基类指针所指向的对象是何种类型,也忽略每一个类的析构函数名的不相同,系统都会为这些对象调用基类的析构函数。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/chusky/archive/2006/02/21/605099.aspx

3,  基类指针与派生类指针的相互转换

(1)基类指针不能直接赋给派生类指针
(2)若使用显示类型转换,则正确使用指针是程序员的责任
(3)由于基类指针指向的是基类对象,强制转换后,派生类指针可以正确访问到基类对象中的数据,
    但是派生类对象的数据实际上是不存在的,若强行访问,则危险。

基类指针,派生类指针,基类对象,派生类对象的混合匹配:
(1),直接用基类指针引用基类对象
(2),直接用派生类指针引用派生类对象
(3),用基类指针引用一个派生类对象,由于派生类对象也是基类的对象,所以这种引用是安全的,
  但是只能引用基类成员。若试图通过基类指针引用那些只在派生类中才有的成员,编译器会报告语法错误。
(解决该问题的答案是虚函数和多态性)
(4),用派生类指针引用基类的对象。这种引用方式会导致语法错误。派生类指针必须先强制转换为基类指针。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/chusky/archive/2006/02/21/605096.aspx

4,volatile(读书笔记)

The grammar of volatile is the same with that of const, but volatile means "this data may
be changed besides the compiler's eyeshot". For some reason, may be multitask, multithread,
interrupt, this data are changed by the enviroment, so we declare it volatile to tell
compiler not to do any optimization on it.
    If the complier says, "I have read the data into a register, and haven't attained to it
since that", in common, it doesn't need to read it any more. But if it was specified by vo-
latile, the compiler must read it again.

//volatile.cpp
//The volatile keyword

class Comm
{
    const volatile unsigned char byte;
    volatile unsigned char flag;
    enum {bufsize = 100};
    unsigned char buf[bufsize];
    int index;
public:
    Comm();
    void isr() volatile;
    char read(int index) const;   
};

Comm::Comm() : index(0), byte(0), flag(0) {}

//Only a demo: won't actually work
//as an interrupt service routine:
void Comm::isr() volatile
{
    flag = 0;
    buf[index++] = byte;
    //Wrap to beginning of buffer:
    if(index >= buffsize)    index = 0;
}

char Comm::read(int index) const
{
    if(index < 0 || index >= bufsize)
        return 0;
    return buf[index];
}

int main()
{
    volatile Comm port;
    port.isr(); //OK
    port.read(0); //Error, read() not volatile
}

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/chusky/archive/2006/02/22/606326.aspx

5.C++中的异常知识点小结

catch(...)捕获所有异常
有时在catch(){}中使用throw;表示不对捕获的异常做任何处理,只是再抛出异常    将throw;空语句放在catch块之外,执行这种throw会调用terminate。
将带void*参数类型的异常处理器放在具有其他指针类型的异常处理器前是个逻辑错误,因为他将捕获所有异常,后面的根本不起作用。
try块不抛出任何异常而正常地执行完毕时,控制传入try块后面最后的一个catch处理器之后的第一条语句而不是try块后的第一条语句
catch块本生也可以抛出异常,但此异常的处理是由外层try块中的异常处理器处理。

异常指定可以由指定函数抛出一列异常:
int g( float h) throw(a, b, c)
{...}

这可以限定从函数抛出的异常类型。事实上这也可以抛出其他异常类型,此时调用unexpected。
若throw()为空,表示不抛出异常,但事实上还是可以抛出异常,不过调用unexcepted利用异常机制可以捕获每格派生类异常对象的指针或引用,但更简练的方法是捕获异常对象的指针和引用。这样可以避免错误。另外我们可以通过设置对象的属性来区分异常

再抛出异常示例:
#include<iostream>
#include<exception>

using namespace std;

void throwException() throw (exception)
{
    try
    {
        cout << "Function throwException\n";
        throw exception();
    }

    catch(exception e)
    {
        cout<<"Exception handled in function throwException\n";
        throw;
    }
}

int main()
{
    try
    {
        throwException();
        cout << "this shoule not print\n";
    }
    catch(exception e)
    {
        cout << "Exception handled in main\n";
    }

    cout << "Program control continues after catch in main" << endl;
    return 0;
}
}

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/chusky/archive/2006/02/22/606334.aspx

6.inline(读书笔记)
inline is a new characteristic in the C++ language. The compiler will check the type of it, if there is not error, the code of the inline function will be put where it is invoked. While the #define macro is processed by the preprocessor, which would not check the type.
      There two restriction:
      1, The inline fuction is too complex, e.g. has loop setences.
      2, The function address is needed explicitly or inexplicitly.
      In this case, the complier will drop the inline, and treat as the common function.
  The inline function is often defined    in the head file, and is treated as static function in those files which inlude this head file, make it local to avoid re-defined errors.

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/chusky/archive/2006/02/21/605091.aspx

7.注意不要返回指向局部变量的指针,因为局部变量存放在栈上面,一旦函数调用结束,则释放。不过静态局部变量除外,其生存期是全局的(第一次执行到该语句时创建,这点与全局(静态)变量不一样),作用域是局部的

抱歉!评论已关闭.