0

在我的代码中,我使用了三个类。所有的类都在单独的文件中。我Makefile用来编译和链接它们。请参阅下面的实现:

class Medicine 
{ 
   int a;
}

class Pain:public Medicine 
{
   int b;
}

class Comb:public Pain   
{
    string salt,com;
}

call()在所有三个类中,所有类都只有参数化的构造函数、虚拟析构函数和同名函数。call()就像_

call()
{
     cout<<"You are in class the_name_of_the_class"<<endl;
}

的代码main.cpp如下:

int main()
{       
    Medicine *p[2];
    p[0]= new Comb("Salt","Com",2,110);
    p[1]= new Comb("SALT","COM",1,100);

    p[0]->call();

    delete p[0];
    delete p[1];
    return 0;
}

当我运行这个程序时,我得到了预期的输出。但是当我将 Medicine::call() 更改为虚拟函数并再次使用make命令时,它说所有文件都是最新的。正如我已经修改medicine.h的那样,make应该创建新版本的medicine.o. 为什么medicine.o在我修改后将旧版本视为已更新medicine.h

Makefile 是这样的:

using .PHONY:clean
OBJ:=medicine.o pain.o comb.o main.o
SOU:=medicine.cpp pain.cpp comb.cpp main.cpp

main:$(OBJ)
        g++ -o $@ $^

%.o:%.cpp
        g++ -c -o $@ $<

clean:
        rm *.o main

如果你想查看medicine.h的实现,

class Medicine
{
    int cost;

 public:

    int getCost();
    void setCost(int);

    Medicine();
    Medicine(int);
    Medicine(Medicine &a);
    virtual string getCompany(){};
    virtual string getSalt(){};
    virtual  ~Medicine ();
    virtual void call();
};

medicine.h已将其包含在 中medicine.cpp,其中定义了所有这些功能。

4

4 回答 4

3

问题是medicine.o只依赖于medicine.cpp,而不是依赖于medicine.h。因此,您必须修改规则以提供缺少的依赖项。它与“虚拟性”完全无关。

您可能还希望将 Makefile 本身添加为依赖项,因此如果您更改它并运行 make,事情就会重新构建。

为了澄清,这个通用规则:

%.o:%.cpp
    g++ -c -o $@ $<

表示 any仅something.o依赖于something.cpp,并且应该使用以下命令构建:

g++ -c -o something.o something.cpp

ie$@是目标名称,$<是第一个依赖项。

格式是

target : <dependencies>
    command
于 2013-08-22T11:20:05.483 回答
1

问题是你的makefile没有你的头文件对源文件的依赖关系,所以当“yh”改变时它不知道你需要重新编译“x.cpp”(因为“yh”被包含通过“x.cpp”)。

您可以通过以下规则来解决此问题:

medicine.o : medicine.cpp medicine.h 

但是,随着源文件的数量越来越大,并且头文件与源文件的关系变得越来越复杂,您将忘记/遗漏一些您实际需要的头文件 - 这总是会发生。

我通常做的是这样的:

SOU = medicine.cpp pain.cpp comb.cpp main.cpp
... 

main:$(OBJ) .depends

...

.depends: $(SOU)
     g++ -MM $(SOU) > $@

include .depends

这样做是让编译器将规则生成到文件.depends中 - 这样,当您在某处更新文件时,您不会“忘记”修复它。

编辑: 对于大型项目,使用单个依赖文件不是一个好主意,因为每次更改 .cpp 文件时,编译器都必须整理项目中每个文件的所有依赖项。但对于一个小的爱好项目来说,这很好。对于大型项目,会有很多.depends文件(每个源文件一个,可能在一个depends目录中)的额外损失。

于 2013-08-22T11:27:00.873 回答
1

make不是语言感知的,所以是的,make 不知道函数是否是虚拟的;实际上它甚至不知道 C++ 是什么以及那里有函数。

make根据目标和依赖关系进行操作,并且必须明确指定。在这里,创建对象的规则不包括.h依赖项中的任何文件,因此它推断.8文件未用于目标。

实际上很难获得构建一个文件所需的适当的传递包含集。.cpp有脚本可以提供帮助,例如make_depend.pl.

于 2013-08-22T11:24:55.503 回答
0

的工作make是这样的:它检查依赖项的最新修改时间(medicine.cpp例如),然后检查创建时间的最新修改medicine.cpp时间。medicine.o如果两者相同,则不重新编译,否则重新编译。在我的情况下,medicine.h被修改了,但最新的修改时间medicine.cpp保持不变。这就是为什么make无法检测到这一点并且没有重新编译的原因medicine.cpp

于 2013-08-22T11:56:09.680 回答