std::ostream 识别而不定义 header
std::ostream recognize without defining header
我创建了这段代码:
Main.cpp
#include <iostream>
#include "Quote.h"
int main()
{
derived().print(std::cout);
getchar();
return 0;
}
Quote.h
#pragma once
#include <string>
class base {
public:
std::string name() { return basename; }
virtual void print(std::ostream &os) { os << basename; }
private:
std::string basename = "abc";
};
class derived : public base {
public:
void print(std::ostream &os) { base::print(os); os << " " << i; }
private:
int i = 0;
};
如果我没有像预期的那样在 Main.cpp 中包含 iostream header 文件,std::cout 无法识别。我的问题是:为什么在 Quote.h if iostream[ 中使用 std::ostream 没有问题=35=]不包括在内?。在上述库中定义了 cout 和 ostream,为什么 cout 使用是一个问题并且 ostream 不是吗?
我正在使用 VS 2017,以防此信息很重要。
header<string>
提供the extraction and insertion operators for std::string
,所以要保证std::ostream
至少是forward-declared;您的代码仅使用对 ostream
的引用,前向声明就足够了,加上前面提到的正确声明的插入运算符。
因此,严格来说,header 已经提供了 header 所需的所有内容,尽管我可能会明确包括 <iosfwd>
明晰。
header <string>
使用 std::ostream
声明输出运算符。您正在使用的实现方式似乎使 std::ostream
普遍可用。
C++ 标准定义了哪些 header 使哪些声明至少可用。它不禁止提供其他名称。不同的实现可能会选择不使声明可用。我曾尝试在我的实现中严格只提供强制声明,但事实证明这并不像听起来那么简单。
您在 header 文件中包含 <string>
。如果您转到 string
header,您将看到第一行(在 VS2017 中):
// string standard header
#pragma once
#ifndef _STRING_
#define _STRING_
#ifndef RC_INVOKED
#include <istream> <----- here
#include <xstring_insert.h>
并前往 istream
header:
// istream standard header
#pragma once
#ifndef _ISTREAM_
#define _ISTREAM_
#ifndef RC_INVOKED
#include <ostream> <-- here
我想这已经回答了你的问题。然而,这是依赖于实现的,你不应该依赖它,而是明确地包含 iostream
header.
Why there's no problem with the use of std::ostream
in Quote.h if <iostream>
is not included?
<iostream>
间接获得 #include
d。
最好不要依赖这种间接 #include
s。您不能指望它在所有平台上都是正确的。它甚至可能从调试版本更改为发布版本。
当您想使用 class 或函数时,最好查找 header 的标准,它应该提供 class 的定义和声明函数,#include
header 直接在您的文件中。
现有答案全部集中在#include <string>
。我想指出另一面。考虑稍作修改的版本:
quote.h
:
#pragma once
// uncomment to get an analog of original example
// #include <string>
struct Quote {};
std::ostream& operator<<(std::ostream& os, Quote const&)
{
return os << "quote\n";
}
main.cpp
:
#include <iostream>
#include "quote.h"
int main()
{
std::cout << Quote{};
}
如您所见,#include <string>
被注释掉了,quote.h
仍然不包含 iostream
,程序仍然可以编译。这是因为只有源文件(.cpp 或翻译单元)是直接编译的。 Headers 确实包括在内。现在,如果我们从字面上将 quote.h
包含在 main.cpp
中,我们将得到:
#include <iostream>
// uncomment to get an analog of original example
// #include <string>
struct Quote {};
std::ostream& operator<<(std::ostream& os, Quote const&)
{
return os << "quote\n";
}
int main()
{
std::cout << Quote{};
}
(online)
这是实际编译的内容。注意这里一切正常,#include <iostream>
在 std::ostream
用法之前。
正如在对 another answer 的评论中正确指出的那样,这就是为什么始终维护 self-sufficient headers 非常重要的一个例子,其中包括它们所依赖的所有 headers .
正如@Evgeny 在评论中指出的,请检查recommendations about organising our includes。
我创建了这段代码:
Main.cpp
#include <iostream>
#include "Quote.h"
int main()
{
derived().print(std::cout);
getchar();
return 0;
}
Quote.h
#pragma once
#include <string>
class base {
public:
std::string name() { return basename; }
virtual void print(std::ostream &os) { os << basename; }
private:
std::string basename = "abc";
};
class derived : public base {
public:
void print(std::ostream &os) { base::print(os); os << " " << i; }
private:
int i = 0;
};
如果我没有像预期的那样在 Main.cpp 中包含 iostream header 文件,std::cout 无法识别。我的问题是:为什么在 Quote.h if iostream[ 中使用 std::ostream 没有问题=35=]不包括在内?。在上述库中定义了 cout 和 ostream,为什么 cout 使用是一个问题并且 ostream 不是吗?
我正在使用 VS 2017,以防此信息很重要。
header<string>
提供the extraction and insertion operators for std::string
,所以要保证std::ostream
至少是forward-declared;您的代码仅使用对 ostream
的引用,前向声明就足够了,加上前面提到的正确声明的插入运算符。
因此,严格来说,header 已经提供了 header 所需的所有内容,尽管我可能会明确包括 <iosfwd>
明晰。
header <string>
使用 std::ostream
声明输出运算符。您正在使用的实现方式似乎使 std::ostream
普遍可用。
C++ 标准定义了哪些 header 使哪些声明至少可用。它不禁止提供其他名称。不同的实现可能会选择不使声明可用。我曾尝试在我的实现中严格只提供强制声明,但事实证明这并不像听起来那么简单。
您在 header 文件中包含 <string>
。如果您转到 string
header,您将看到第一行(在 VS2017 中):
// string standard header
#pragma once
#ifndef _STRING_
#define _STRING_
#ifndef RC_INVOKED
#include <istream> <----- here
#include <xstring_insert.h>
并前往 istream
header:
// istream standard header
#pragma once
#ifndef _ISTREAM_
#define _ISTREAM_
#ifndef RC_INVOKED
#include <ostream> <-- here
我想这已经回答了你的问题。然而,这是依赖于实现的,你不应该依赖它,而是明确地包含 iostream
header.
Why there's no problem with the use of
std::ostream
in Quote.h if<iostream>
is not included?
<iostream>
间接获得 #include
d。
最好不要依赖这种间接 #include
s。您不能指望它在所有平台上都是正确的。它甚至可能从调试版本更改为发布版本。
当您想使用 class 或函数时,最好查找 header 的标准,它应该提供 class 的定义和声明函数,#include
header 直接在您的文件中。
现有答案全部集中在#include <string>
。我想指出另一面。考虑稍作修改的版本:
quote.h
:
#pragma once
// uncomment to get an analog of original example
// #include <string>
struct Quote {};
std::ostream& operator<<(std::ostream& os, Quote const&)
{
return os << "quote\n";
}
main.cpp
:
#include <iostream>
#include "quote.h"
int main()
{
std::cout << Quote{};
}
如您所见,#include <string>
被注释掉了,quote.h
仍然不包含 iostream
,程序仍然可以编译。这是因为只有源文件(.cpp 或翻译单元)是直接编译的。 Headers 确实包括在内。现在,如果我们从字面上将 quote.h
包含在 main.cpp
中,我们将得到:
#include <iostream>
// uncomment to get an analog of original example
// #include <string>
struct Quote {};
std::ostream& operator<<(std::ostream& os, Quote const&)
{
return os << "quote\n";
}
int main()
{
std::cout << Quote{};
}
(online)
这是实际编译的内容。注意这里一切正常,#include <iostream>
在 std::ostream
用法之前。
正如在对 another answer 的评论中正确指出的那样,这就是为什么始终维护 self-sufficient headers 非常重要的一个例子,其中包括它们所依赖的所有 headers .
正如@Evgeny 在评论中指出的,请检查recommendations about organising our includes。