可以使用继承来减少C ++中编译代码的大小吗?

时间:2017-03-24 18:43:33

标签: c++ c++11 inheritance size

我正在开发一个基于Arduino的系统(即嵌入式系统)的项目,并且代码的ROM数量有限。

我发现自己需要几种不同类型的集合类(例如ListStackQueue)。 写完这些之后,我注意到除了使它们表现不同的特征(例如Add vs Push vs EnqueuePop vs Dequeue)之外,它们共享一个许多常见功能(例如,它们具有完全相同的字段)。

这让我想到,如果我要创建一个包含其他类的所有常用功能的基类(让我们称之为Collection)并使其他类继承它,并让它们只实现不同的功能,这会导致编译代码更少吗?

我期待它会因为子课程都可以参考父母对常用功能的实现,但我可能是错的,所以在尝试这个改变之前我宁愿问一下。

好的,为了进一步澄清这一点,因为人们似乎误解了,请考虑这些假设的课程:

class A
{
protected:
    int value;
public:
    void assign(int other)
    {
        this->value = other;
    }
}

class B : public A
{
public:
    void assignAdd5(int other)
    {
        this->value = other + 5;
    }
}

然后是代码:

A a = A();
B b = B();

a.assign(4);
b.assign(4);

我期望assign在两种情况下都引用相同的方法(因此编译的代码块相同),尽管类型不同,因为BA的子类。如果是这种情况,那么具有类似功能的类都将从实现相似性的单个基类继承,这将产生比使每个类单独实现功能更少的编译代码,因为每个子类将使用相同的函数。

我提供的有关提示此问题的情况的信息仅仅是背景,我知道是否是任何编译器的情况,而不仅仅是我使用的那个(和我完全明白,答案可能是“有些编译器可能会这样做,但并非所有编译器都这样做,而且这是一个完全可以接受的答案。”

2 个答案:

答案 0 :(得分:1)

我无法给出明确答案,但我想分享我的发现。实际上我并不像我预期的那样容易衡量差异。不要把代码太严肃,我只是尝试随机的东西,看它是否有任何影响...

#include <iostream>
#define DERIVED
#define BASE_STUFF     int a,b,c,d,e,f,g,h,i,k,m,n,o,p,q,r,s,t,u,v,w,x,y,z; \
                       double foo1(int x){return x;}                        \
                       double foo2(int x){return x;}                        \
                       double foo3(int x){return x;}                        \
                       double foo4(int x){return x;}                        \
                       Base*  foo5(Base* x){return x;}                      \
                       FPTR   foo5(FPTR a,FPTR b,FPTR c){return a;}

typedef double (*FPTR)(int,int,double);

struct Base { BASE_STUFF };

#ifdef DERIVED
struct Derived : Base{double a0,a1,a2,a3,a4,a5,a6,a7;};
#endif

#ifndef DERIVED
struct Derived {
    double a0,a1,a2,a3,a4,a5,a6,a7;
    BASE_STUFF
};
#endif

int main(int argc, char *argv[])
{
    Base b;
    b.x = 1;
    std::cout << b.foo1(b.x);
    std::cout << b.foo5(&b)->foo2(b.a);
    Derived n;
    n.a0 = 2;
    std::cout << n.foo1(n.a0);
}

我必须再次检查数字,但令我惊讶的是,与c风格iostream相比,使用prinft时可执行文件更小。

当我用(g ++ 4.9.2)

编译时
g++ main.cpp -Os -fno-exceptions -s

我得到了13.312 kB的可执行文件。这与被定义的DERIVED无关。但是,当我用

编译它时
g++ main.cpp -Os -fno-exceptions

大小为43.549 kB。再次独立于DERIVED被定义与否。

我的结论是

  • 我的例子不适合衡量差异
  • ...然而,尝试使用编译器标志会产生巨大的差异,而继承与否则没什么区别
  • 我不会改变设计,以减少代码大小。编写代码,以便在需要从exe中挤出一些KB时,易于读取,编写,使用和使用编译器标志(另请参阅here

答案 1 :(得分:0)

写一个完整的容器。

私下继承它。使用using将要公开的方法带入视图。

编译器最多会为dtor / ctor创建一些极短的方法。