Java C++;:如何在独立的源文件上定义类,然后在主程序中使用它们?

Java C++;:如何在独立的源文件上定义类,然后在主程序中使用它们?,java,c++,class,oop,package,Java,C++,Class,Oop,Package,我不太熟悉OOP,有些东西对我来说太暗了 (我在java上学习OOP课程,但我想学习C++),我发现我们可以在同一个包上定义独立文件类,然后在我们的项目中自由使用它们。 C++中是否有任何等价于java的包?我可以在主程序的源文件中包含唯一定义的类吗 P>因为我对这个话题很陌生,请你纠正我,如果我有什么词汇错误,我需要的是知识:D Shanx< P>因为有一些人不喜欢发布链接,下面是你的问题的详细答案,它可以深入解释C++“等价”到java包(命名空间)。如果希望以更可读的格式查看信息,请访

我不太熟悉OOP,有些东西对我来说太暗了

(我在java上学习OOP课程,但我想学习C++),我发现我们可以在同一个包上定义独立文件类,然后在我们的项目中自由使用它们。

C++中是否有任何等价于java的包?我可以在主程序的源文件中包含唯一定义的类吗


<> P>因为我对这个话题很陌生,请你纠正我,如果我有什么词汇错误,我需要的是知识:D Shanx

< P>因为有一些人不喜欢发布链接,下面是你的问题的详细答案,它可以深入解释C++“等价”到java包(命名空间)。如果希望以更可读的格式查看信息,请访问以下链接:

C++中的包:名称空间 包是一个命名的声明集合,可以跨越多个文件(参见第1章)。包定义了它所包含的声明的范围,可以分为接口包和实现包

C++提供了几种类型的作用域:全局、文件、类和块。我们还可以使用命名空间声明创建包范围:

void test2()
{
 using Car::test;
 Car::Buick b;
 Car::Ford f;
 test(b);
 test(f);
}
命名空间名称{声明…}

对命名空间之外名称的引用必须使用范围解析运算符限定。例如,假设在名为Planet:[1]的命名空间中声明了一个名为jupiter()的函数

namespace Planet 
{
void jupiter() { ... } 
 // etc.
}
Planet命名空间的客户端必须限定对jupiter()的调用:

行星:木星()

相比之下:

namespace RomanGods 
{
void jupiter() { ... } 
// etc.
}
命名空间的客户端必须限定对jupiter()的调用:

罗马神:朱庇特()

<> P>标准C++库中的所有声明都包含在名为STD的命名空间中。这意味着头文件中定义的名称,如OFFROST、ISTRAM、CUT,以及CIN在客户端使用它们时必须符合“STD::”(见编程注释A.3)。例如,以下是Hello world计划的官方版本:

#include <iostream>
int main()
{
 std::cout << "Hello, world!\n";
 return 0;
}
#include <iostream>
using namespace std;
int main()
{
 cout << "Hello, world!\n";
 return 0;
}
链接器并没有因为Car名称空间的两个独立声明而感到不安。相反,它认为第二个“宣言”是第一个“宣言”的延续

实现在ford.cpp和buick.cpp文件中。请注意,成员函数的名称由命名空间名称和类名限定:

// buick.cpp
#include "buick.h"
#include <iostream>
void Car::Buick::start() { std::cout << "Starting a Buick\n"; }
void Car::Buick::drive() { std::cout << "Driving a Buick\n"; }
void Car::Buick::stop() { std::cout << "Stopping a Buick\n"; }
void Car::test(Buick c) { c.start(); c.drive(); c.stop(); }

// ford.cpp
#include "ford.h"
#include <iostream>
void Car::Ford::start() { std::cout << "Starting a Ford\n"; }
void Car::Ford::drive() { std::cout << "Driving a Ford\n"; }
void Car::Ford::stop() { std::cout << "Stopping a Ford\n"; }
void Car::test(Ford c) { c.start(); c.drive(); c.stop(); }
test1()为Car命名空间中声明的所有项使用限定名:

void test1()
{
 Car::Buick b;
 Car::Ford f;
 Car::test(b);
 Car::test(f);
}
test2()使用using声明将名称Car::test导入其作用域:

void test2()
{
 using Car::test;
 Car::Buick b;
 Car::Ford f;
 test(b);
 test(f);
}
using声明有点像import声明,但它只允许从声明点到声明发生的作用域的末尾无条件地使用test()函数。在这种情况下,声明发生在块范围内。换句话说,test1()函数仍然必须使用“Car::”限定对test()的调用,即使它是在test2()之后声明的。还要注意,我们不能导入test()函数的一个变量,但不能导入另一个变量

test3()使用using指令将整个Car命名空间导入其作用域:

void test3()
{
 using namespace Car;
 Buick b;
 Ford f;
 test(b);
 test(f);
}
与using声明一样,using指令只允许在其发生的范围内对命名空间名称进行非限定引用

通常会将整个std命名空间导入到文件范围中,以避免需要限定对库类型或对象的每个引用。以下是我们新实施的Hello world计划:

#include <iostream>
int main()
{
 std::cout << "Hello, world!\n";
 return 0;
}
#include <iostream>
using namespace std;
int main()
{
 cout << "Hello, world!\n";
 return 0;
}
选择通过从现有命名空间中选择项来创建新命名空间:

namespace FarmJobs
{
 void plant() { cout << "planting corn\n"; }
 void grow() { cout << "growing corn\n"; }
 void pick() { cout << "picking corn\n"; }
}

namespace OfficeJobs
{
 void file() { cout << "filing reports\n"; }
 void type() { cout << "typing reports\n"; }
 void shred() { cout << "shredding reports\n"; }
}
namespace Jobs
{
 using namespace FarmJobs;
 using namespace OfficeJobs;
}
namespace EasyJobs
{
 using FarmJobs::grow;
 using OfficeJobs::file;
 using OfficeJobs::shred;
}
客户可以在不了解农场工作或办公室工作的情况下使用Jobs和EasyJobs:

void test5()
{
 Jobs::plant();
 Jobs::grow();
 Jobs::pick();
 Jobs::type();
 Jobs::file();
 Jobs::shred();
 EasyJobs::grow();
 EasyJobs::shred();
}
示例3:名称空间作为接口

与头文件一样,命名空间指定客户端和实现者的接口。实现者的接口包含所有声明:

// register.h
namespace Register // cash register functions
{
 void recordItem();
 void computeTotal();
 void makeReceipt();
 void reset();
 void lock();
 void unlock();
}
与往常一样,我们将实现与接口分开:

// register.cpp
#include "register.h"
void Register::recordItem() { ... }
void Register::computeTotal() { ... }
void Register::makeReceipt() { ... }
void Register::reset() { ... }
void Register::lock() { ... }
void Register::unlock() { ... }
// manager.cpp
#include "manager.h"
#include "register.h"
void ManagerInterface::unlock() { Register::unlock(); }
void ManagerInterface::reset() { Register::reset(); }
void ManagerInterface::lock() { Register::lock(); }
假设我们预期两种类型的客户:职员和经理。通过选择,我们可以为每个客户端创建客户端接口:

// clerk.h
#include "register.h"
namespace ClerkInterface
{
 using Register::recordItem;
 using Register::computeTotal;
 using Register::makeReceipt;
 using Register::reset;
}

// manager.h
#include "register.h"
namespace ManagerInterface
{
 using Register::unlock;
 using Register::lock;
 using Register::reset;
}
示例4:名称空间之间的委托[2]

我们可以消除管理器接口的依赖性,例如,通过提供委托给相应寄存器函数的管理器接口函数的实现来消除对寄存器接口的依赖性:

// manager.h
namespace ManagerInterface
{
 void unlock();
 void lock();
 void reset();
}
当然,manager接口的实现仍然取决于register接口:

// register.cpp
#include "register.h"
void Register::recordItem() { ... }
void Register::computeTotal() { ... }
void Register::makeReceipt() { ... }
void Register::reset() { ... }
void Register::lock() { ... }
void Register::unlock() { ... }
// manager.cpp
#include "manager.h"
#include "register.h"
void ManagerInterface::unlock() { Register::unlock(); }
void ManagerInterface::reset() { Register::reset(); }
void ManagerInterface::lock() { Register::lock(); }

不清楚你在问什么。C++通常使用包含类声明(包括使用代码的类声明)的头文件,以及包含类的定义(实现)的编译单元(<代码> .CPP < /代码>)。java包最合适的等价物似乎是库(预编译编译单元)+它们相应的头文件集。