In my code, I have used three classes. All the classes are in separate files. And I am using Makefile
to compile and link them. See the implementation below:
class Medicine
{
int a;
}
class Pain:public Medicine
{
int b;
}
class Comb:public Pain
{
string salt,com;
}
All classes have just parameterized constructors, virtual destructors and a function with same name call()
, in all the three classes. And call()
is like
call()
{
cout<<"You are in class the_name_of_the_class"<<endl;
}
The code of main.cpp
goes like:
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;
}
When I run this program, I got the expected output. But when I changed the Medicine::call() to be a virtual function, and again used make
command, it says all files are up to date. As I have modified medicine.h
, so make
should created new version of medicine.o
. Why is it considering older medicine.o
as updated when I have modified medicine.h
?
The Makefile goes like this:
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
If you want to see implementation of 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();
};
This medicine.h
I have included in medicine.cpp
, where all these functions are defined.
The problem is that medicine.o
only depends on medicine.cpp
, not on medicine.h
. So you have to modify your rules to provide that missing dependency. It has absolutely nothing to do with "virtualness".
You might also want to add the Makefile itself as a dependency, so if you change it and run make, things get re-built.
To clarify, this generic rule:
%.o:%.cpp
g++ -c -o $@ $<
means that any something.o
depends on something.cpp
only, and should be built with the following command:
g++ -c -o something.o something.cpp
ie $@
is the target name and $<
is the first dependency.
the format is
target : <dependencies>
command
make
is not language-aware, so yes, make does not know whether a function is virtual or not; actually it does not even know what C++ is and that there are functions there.
make
operates in terms of targets and dependencies, and those have to be specified explicitly. Here, the rule to make an object does not include any .h
file in the dependencies and thus it deduces that .8
files are unused for the target.
It is actually quite difficult to get the proper set of transitive includes needed to build one .cpp
file. There are scripts to assist such as make_depend.pl
.
The problem is that your makefile doesn't have the dependencies for your header files to the source files, so it doesn't know that you need to recompile "x.cpp" when "yh" has changed (because "yh" is included by "x.cpp").
You can fix that by having rules like:
medicine.o : medicine.cpp medicine.h
However, as the number of source files get larger, and the relationship of headers to source gets more complex, you are going to forget/leave out some header files that you actually need - this will ALWAYS happen.
What I usually do is something like this:
SOU = medicine.cpp pain.cpp comb.cpp main.cpp
...
main:$(OBJ) .depends
...
.depends: $(SOU)
g++ -MM $(SOU) > $@
include .depends
What this does is to let the compiler generate the rules into a file .depends
- that way, you don't "forget" to fix it up when you update a file somewhere.
Edit: For large projects, using a single dependency file is a poor idea, because every time a .cpp file is changed, the compiler will have to sort out all the dependencies for every file in the project. But for a small hobby project it's fine. For large projects, one would take the extra penalty of having lots of .depends
files (one per source file, probably in a depends
directory).
The working of make
is like this: It checks the latest modification time of the dependency ( medicine.cpp
for eg) and then check the latest modification time of medicine.cpp
when medicine.o
was created. If both are same, then its not recompiled, otherwise recompiled. In my case, medicine.h
was modified, but the latest modification time of medicine.cpp
remain unchanged. And that's why make
was unable to detect this and not recompiled medicine.cpp
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.