-1

我在为我的问题 (Q) 找到答案时遇到了麻烦,所以我在这里注册以询问你们它是如何真正起作用的(或不起作用);)

我在 Visual Studio 2012 中用 c++ 编写,但仍然不知道头文件中的#includes、命名空间等如何。我什至需要使用它们吗?

(Q1):假设我有一个 .cpp 文件和几个 .h 文件,它们正在使用例如:向量、来自 <algorithm>、<ctime> 和其他一些库的东西,但我不写 #include <something > 在头文件中,仅在 .cpp 中。这是对的吗?或者我应该在每个标题中包含我使用的所有内容?

通常一切都对我有用,我什至可以说它总是“有效”,因为我还没有太多经验,而且我通常将所有内容包含在一个 .cpp 和 1 或 2 个带有一些 void 函数的标题中。但是不知道它是否有效,因为它应该,或者因为例如 mu 编译器允许这样做,并且在某些问题中它可能会导致错误。

(Q2):现在关于使用命名空间std的事情;在某些情况下,.h 文件中的函数可以在没有它的情况下工作,但有时不能。例如,正在工作的空位(只是合并排序的简单空位):

#ifndef LISTA_1_H
#define LISTA_1_H

#include "Lista_0_Zadanie_1.h"

void MERGE(vector<double> &A, int p, int q, int r)
{
int i = p;
int j = q+1;
int lenght = r - p + 1;
int k=0;
vector<double> merged;
merged.assign (lenght,0);
while((i<=q)&&(j<=r))
    {   
    if(A[i] <= A[j])
        {
        merged[k]=A[i];
        ++i;
        }
    else
        {
        merged[k]=A[j];
        ++j;
        }
    k++;
    }

if(j<=r)
    {
    while(j<=r)
        {
        merged[k]=A[j];
        ++j;
        ++k;
        }
    }
if(i<=q)
    {
    while(i<=q)
        {
        merged[k]=A[i];
        ++i;
        ++k;
        }
    }
for (i=0;i<lenght;++i)
    A[p+i]=merged[i];
}


void MERGESORT(vector<double> &A, int k, int l) 
{
if(k<l)
    {
    int m = (k+l)/2;
    //int mp = m+1;
    //  cout << "koza"<<endl;
    MERGESORT(A,k,m);
    MERGESORT(A,m+1,l);
    MERGE(A,k,m,l);
    }
}

void TRIPLE_MERGESORT(vector<double> &A, int k, int l)  
{
if(k<l)
    {
    int one_third = (l-k)/3;
    int two_third = 2*(l-k)/3;          // k < k+one_third < k+two_third < l
    TRIPLE_MERGESORT(A,k,k+one_third);
    TRIPLE_MERGESORT(A,k+one_third+1,k+two_third);
    TRIPLE_MERGESORT(A,k+two_third+1,l);
    MERGE(A,k,k+one_third,k+two_third);
    MERGE(A,k,k+two_third,l);
    }
}

void INSERT_MERGESORT (vector<double> &A, int k, int l)
{
if(l<19)        // l=n-1, więc n<20 <=> l < 19
    {
    double y;
    int i,j;
    for(i=0; i<l+1; ++i)
        {
        y = A[i];
        j = i-1;
        while((j>=0) && (A[j]>y) )
            {
            A[j+1] = A[j];          
            --j;
            }
        A[j+1]=y;
        }
    }
else
    MERGESORT(A,k,l);
}

#endif

...并且在某些情况下,如果我不写“使用命名空间 std;”,它就不起作用 或在正确的位置添加“ std:: ”(在向量之前),它不起作用:

#ifndef SCHEMAT_HORNERA_H
#define SCHEMAT_HORNERA_H
//using namespace std;

 void HORNER( int n, double z0, double p_z0, vector<double> a, vector<double> &B)
{
B[n] = a[n];

for(int k = n-1; k>=0; --k)
    {
    B[k] = a[k] + z0*B[k+1];
    }   
}
#endif

所以这是我的问题:我应该总是使用“std::”还是“using namespace std”?如果是,为什么我的文件直到现在“工作”?因为在某些情况下 VS 允许这样做,虽然它不正确并且某些编译器不允许这样做?

4

2 回答 2

1

Q1)您是否需要#include具有完整定义的标题取决于您是否需要完整定义,或者是否只需要前向声明。在只需要前向声明的情况下,您需要告诉编译器的只是某物的名称。一个例子是如果你需要一个指向某物的指针:

// fw-decl Foo
class Foo;

// define Gizmo
class Gizmo
{
public:
  void DoIt();
  Foo* mFoo;  // just need a pointer, so don't need a full definition of foo
};

稍后,如果您实际使用该Foo对象,您将需要一个完整的定义,如下所示:

#include "foo.h"
#include "gizmo.h"

void Foo::DoIt()
{
  mFoo->DoSomething(); // now we need a full definition
}

另一方面,如果编译器需要知道例如Foo有多大,那么您需要一个完整的定义。

#include "foo.h"

class Gizmo
{
public:
  Foo mFoo;  // need a full definition here
};

作为一般经验法则,最好仅在必要时提供完整定义,以尽可能缩短编译时间。

Q2) 简化的经验法则:从不using namespace std。如果您只是遵循这个经验法则而不考虑它,您将永远不会遇到命名空间冲突、污染全局命名空间或其他讨厌的问题。

当然,对于那些真正以谋生为生的人来说,这个经验法则有点过于简单,所以这里有一个稍微好一点的法则:

1) 永远不要using namespace出现在标题中 2) 永远不要using namespace出现在源文件中,除非它是您正在实现的自己的命名空间。

经验法则可能过于严格,这也不例外,但它会让你在不冒险太远进入地雷的情况下顺利上路。问题using anmespace在于它将该名称空间中的任何内容带入全局范围。假设你有自己的头文件:

我的字符串.h

namespace MyString
{
    class string
    {
      // ...
    };
}

...然后在源文件中:

#include "mystring.h"
#include <string>

using namespace MyString;
using namespace std;

string s;  // OOPS:  which "string" is this?  MyString::string, or std::string?

这种模糊性在这里很明显,但在现实世界中它可能不那么明显,并导致一些非常难以检测的错误。

于 2013-05-22T15:05:50.300 回答
0

(Q1) 重要的是要记住包含声明的实际作用。基本上,它只不过是包含在新文件中的整个文件的简单复制/粘贴。

由于头文件包含在许多地方,因此通常不赞成在 .h 文件中包含许多不必要的包含(除非使用模板)。通常,当前向声明就足够时,不要包含在头文件中。

在 .cpp 文件中,包括所有必要的文件,以便程序可以编译。

因为您使用的是 Visual Studio,所以必须小心,因为它对包含您实际上忘记包含的标准库中的文件非常宽松,并且您可能会在其他系统上编译时遇到问题。

(Q2)在头文件中,您不应该有“使用”语句。请记住,include 语句是一个简单的复制/粘贴;因此,如果你有一个 using 语句,它也将包含在新文件中。

在 .h 文件中,您应该始终使用 std::vector、std::set 等。

在 .cpp 文件中,可以使用命名空间 std、使用 std::vector 等。

(边栏)与您的代码相关,您应该将其拆分为头文件和 cpp 文件。.h 文件中没有定义,只有声明。制作一个 .cpp 文件并在其中定义算法。也不要在 .cpp 文件中定义保护。永远不要包含 .cpp 文件!

于 2013-05-22T15:39:15.100 回答