我有一个作业,我需要根据GRASP“ Protected Variation”评估哪种方法更好。我在Stack Overflow上发现了一个有关C ++中的头文件和代码文件分离的问题。
但是,我想知道为什么Java在促进类定义和类实现之间的分离时不遵循C ++。与C ++方法相比,Java方法有什么优势吗?
private
以便实现知道大小,并且private
成员函数也应知道。
我有一个作业,我需要根据GRASP“ Protected Variation”评估哪种方法更好。我在Stack Overflow上发现了一个有关C ++中的头文件和代码文件分离的问题。
但是,我想知道为什么Java在促进类定义和类实现之间的分离时不遵循C ++。与C ++方法相比,Java方法有什么优势吗?
private
以便实现知道大小,并且private
成员函数也应知道。
Answers:
以下程序中有几行代码?
#include <iostream>
int main()
{
std::cout << "Hello, world!\n";
return 0;
}
您可能回答了7(如果不计算空白行,则为6;如果不计算括号,则为4)。
但是,您的编译器会看到非常不同的东西:
~$ cpp hello.cpp | wc
18736 40822 437015
是的,这是18.7 KLOC,仅用于“您好,世界!” 程序。C ++编译器必须解析所有这些内容。这是为什么C ++编译与其他语言相比要花这么长时间的主要原因,也是现代语言避开头文件的主要原因。
一个更好的问题是
C ++被设计为C的超集,因此必须保留头文件以实现向后兼容性。
由于其原始的独立编译模型。C编译器生成的目标文件不包含任何类型信息,因此,为了防止类型错误,您需要在源代码中包含此信息。
~$ cat sqrtdemo.c
int main(void)
{
/* implicit declaration int sqrt(int) */
double sqrt2 = sqrt(2);
printf("%f\n", sqrt2);
return 0;
}
~$ gcc -Wall -ansi -lm -Dsqrt= sqrtdemo.c
sqrtdemo.c: In function ‘main’:
sqrtdemo.c:5:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
sqrtdemo.c:5:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
~$ ./a.out
2.000000
添加正确的类型声明可修复该错误:
~$ cat sqrtdemo.c
#undef printf
#undef sqrt
int printf(const char*, ...);
double sqrt(double);
int main(void)
{
double sqrt2 = sqrt(2);
printf("%f\n", sqrt2);
return 0;
}
~$ gcc -Wall -ansi -lm sqrtdemo.c
~$ ./a.out
1.414214
请注意,没有#include
。但是,当您使用大量外部函数(大多数程序会使用)时,手动声明它们会变得乏味且容易出错。使用头文件要容易得多。
通过使用包含类型信息的其他目标文件格式。例如,Java * .class文件格式包括指定字段类型和方法参数的“描述符”。
这不是一个新发明。早在(1987年),当Borland在Turbo Pascal 4.0中添加了单独编译的“单元”时,它选择使用一种新*.TPU
格式而不是Turbo C *.OBJ
来消除对头文件的需要。
OBJ
文件而不是TPU
s ...
Java具有定义合同的接口。这从调用者的需求和实际实现中提供了更高层次的抽象。也就是说,调用者不需要知道实现类,只需要知道它支持的协定即可。
假设您想编写一种减慢Map中所有键/值的方法。
public static <K,V> void printMap(Map<K,V> map) {
for(Entry<K,V> entry: map.entrySet())
System.out.println(entry);
}
此方法可以在抽象接口上调用entrySet(),该接口已从实现该接口的类中移除。您可以使用此方法。
printMap(new TreeMap());
printMap(new LinkedHashMap());
printMap(new ConcurrentHashMap());
printMap(new ConcurrentSkipListMap());
#define interface class
。
virtual
关键字来获取多态性,并且如果您仅使用一种或两种具体类型(例如Java中的具体类型),则不会对性能造成任何影响。您能指出我有关C ++如何工作的任何文档吗?
Java确实促进了类定义和实现的分离,这仅取决于您要查找的位置。
当您是Java类的作者时,您会在一个文件中看到该类的定义及其实现。这简化了开发过程,因为您只需要去一个地方维护类,就不必在两个文件之间切换(就像在C ++中那样,在.h和.cpp之间)。但是,当您是该类的使用者时,您只能通过打包在.jar或独立.class中的.class文件来处理定义。
C ++允许您将定义和实现分开,但这是临时的。例如,没有什么可以阻止您在头文件中内联编写方法,对于模板类,这是强制性的。头文件还列出了所有成员变量,即使这些成员变量是该类的实现细节,并且与使用者无关,所有查看该头文件的人都可以看到它们。