之所以C++有时不被当作高级语言,那是因为它是一门对变量内存布局很讲究的语言,每个变量所占用的空间大小如果发生变化,有时候是会影响程序的结果的。例如在同时使用多态对象和数组技术时,就容易出现这样的问题。

我们首先来看看高级语言C#写的一段小程序:

csharp
 1using System;
 2using System.Collections.Generic;
 3
 4namespace Test
 5{
 6    class Base
 7    {
 8        public virtual void Foo() { Console.WriteLine("From Base"); }
 9    }
10
11    class Derived : Base
12    {
13        public override void Foo() { Console.WriteLine("From Derived"); }
14    }
15
16    class Program
17    {
18        static void Main(string[] args)
19        {
20            List<Base> a = new List<Base>();
21            a.Add(new Base());
22            a.Add(new Derived());
23
24            foreach (Base b in a)
25            {
26                b.Foo();
27            }
28        }
29    }
30}

程序的执行结果是:

text
1From Base
2From Derived

很简单的程序,把基类和派生类分别实例化出来的对象放入列表中,然后逐个取出来。结果也如同我们所预料的那样,分别执行了基类和派生类的成员函数(方法)。然而到了C++中,却没有那么理想了:

cpp
 1#include <iostream>
 2#include <vector>
 3
 4class Base
 5{
 6    public:
 7        virtual void Foo() { std::cout << "From Base" << std::endl; }
 8};
 9
10class Derived : public Base
11{
12    public:
13        virtual void Foo() { std::cout << "From Derived" << std::endl; }
14};
15
16int main()
17{
18    std::vector<Base> a;
19    a.push_back(Base());
20    a.push_back(Derived());
21
22    for (size_t i = 0; i < a.size(); i++)
23    {
24        a[i].Foo();
25    }
26    return 0;
27}

程序的执行结果是:

text
1From Base
2From Base

原来,被放入列表后,派生类对象也被“截断”成为基类对象,因而只能调用到基类的成员函数了。这就是C++中一个很重要的原则:**想要实现多态,必须使用指针或引用!**这在《More Effective C++》中也有详细地阐述(“条款3:不要使用多态性数组”)。然而,引用是无法放入列表容器中的,因此只能使用对象指针的数组:

cpp
 1// ...
 2// Base 和 Derived 类定义同前
 3// ...
 4int main()
 5{
 6    std::vector<Base*> a;
 7    a.push_back(new Base());
 8    a.push_back(new Derived());
 9
10    for (size_t i = 0; i < a.size(); i++)
11    {
12        a[i]->Foo();
13    }
14
15    for (size_t i = 0; i < a.size(); i++)
16    {
17        delete a[i];
18    }
19    return 0;
20}

这时结果就符合我们的预期了:

text
1From Base
2From Derived

但比较麻烦的是,我们必须在结束使用这些 new 出来的对象时,用 delete 逐个销毁它们。所幸,boost 中有一利器:boost::shared_ptr,能帮我们分担点这方面的焦虑:

cpp
 1// ...
 2#include <boost/shared_ptr.hpp>
 3// ...
 4// Base 和 Derived 类定义同前
 5// ...
 6int main()
 7{
 8    std::vector<boost::shared_ptr<Base>> a;
 9    a.push_back(boost::shared_ptr<Base>(new Base()));
10    a.push_back(boost::shared_ptr<Base>(new Derived()));
11
12    for (size_t i = 0; i < a.size(); i++)
13    {
14        a[i]->Foo();
15    }
16    return 0;
17}

所以,强烈期盼 boost 早日成为众多 C++ 编译器的标准支持!