为什么不需要资格?
Why is no qualification necessary?
好的,我将发布完整的程序尽管它有一些无关的东西并且问题代码是死代码& help;
#include <iostream>
#include <fstream>
namespace detail {
// Solution by Johannes Schaub alias litb
// http://groups.google.com/group/comp.std.c++/browse_thread/thread/b567617bfccabcad
template<int> struct D {};
typedef char yes[1];
typedef char no[2];
template< class T, class U >
yes& f( int, D< sizeof T(*(U*)0) >* = 0 );
template< class T, class U >
no& f( ... );
template< class To, class From >
struct IsExplicitlyConvertible
{
enum{ yes = (sizeof detail::f< To, From >(0) == sizeof( detail::yes ) ) };
};
bool const streamsSupportWindows =
IsExplicitlyConvertible< std::ofstream, wchar_t const* >::yes;
}
class InFStream
: public std::ifstream
{
public:
InFStream() {}
explicit InFStream(
char const* filename,
ios_base::openmode mode = ios_base::in | ios_base::out
)
: std::ifstream( filename, mode )
{}
};
int main()
{
using namespace std;
cout << (detail::streamsSupportWindows
? "Windows-enabled"
: "Ach, no Windows support"
) << endl;
}
在MSVC和g++中可以很好地编译。但是在InFStream
课程中,为什么我不需要符合ios_base
?或者,同样的问题,为什么我需要在构造函数初始化列表中使用ifstream
的std::
限定?
不同的是,ifstream
作为注入类名是不可见的,因为它是typedef
的名称,而不是class
的名称。因此,作为基类注入的类名,它是不可见的。
ios_base
是一个真正的类名,它是使用它的类的基类(基类的基类),因此作为注入类名是不合格的。
。
namespace X
{
class A {};
template<class> class Z {};
typedef Z<char> B;
}
class C : public X::A
{
C() : A() {} // OK, A is visible from the base class
};
class D : public X::B
{
D() : B() {} // Error, B is a typedef,
// : X::B(), : Z<char>() or even : Z() can be used.
};
在您的示例中,您可以使用不限定的basic_ifstream
代替std::ifstream
。(或basic_ifstream<char>
或basic_ifstream<char, std::char_traits<char> >
,但这些并不能真正节省任何输入或帮助清晰。)
关于为什么必须在构造函数的初始化项中指定std::ifstream
的一些想法。我认为typedef
是罪魁祸首——ifstream
被定义为typedef basic_ifstream<char, char_traits<char> > ifstream;
)。如果将构造函数更改为
explicit InFStream(
char const* filename,
ios_base::openmode mode = ios_base::in | ios_base::out
):
basic_ifstream<char,std::char_traits<char>>( filename, mode ){}
也不需要指定std::basic_ifstream
。我找不到typedef
为什么这样工作的细节,但问题是可重复的。例如,
namespace test1
{
class A {
public :
static const int cn = 1;
virtual ~A();
A(int t): x(t){};
int x;
};
class B:public A
{
public:
B(int t) : A(t){};
};
typedef B XX;
};
class C:public test1::XX
{
int aaa;
public:
explicit C(int x) :XX(x) // error
explicit C(int x) :test1::XX(x) // ok
explicit C(int x) :B(x) // also ok
{
aaa = A::cn;
};
};
另一个观察是ios_base::openmode工作,但ios::openmode不能:
class InFStream
: public std::ifstream
{
// ...
ios::openmode m1; // error: ios does not name a type
ios_base::openmode m2; // ok
}
我认为a1ex07已经找到了问题的关键:在这里,ios_base
是一个类的名称,而ios
仅仅是一个类型定义。
区别在于类的名称是该类(9/2)的成员,因此可以作为InFStream
(3.4.1/7 item 1)中的类型名称查找,因为它是InFStream
的基类的成员。但是有些类型定义仅仅与基类一起出现在其他命名空间中是看不到的。
当您从类中派生时,您必须指定
std::ifstream
能够在STD命名空间中找到类。
在代码中,从std::ifstream派生的类知道ifstream的一切。
继承ifstream:
ios_base -> ios -> istream -> ifstream
- 为什么output_editor Concept不需要output_e迭代器标记
- 与C代码相比,为什么C++代码不需要"#define _POSIX_C_SOURCE 200809L"?
- 为什么转换函数声明不需要至少一个定义类型说明符
- 我不明白为什么我的代码不起作用并且需要更长的时间来运行
- 为什么python需要全局关键字而C/C++不需要?
- 为什么我们需要在 C++ 中检查空指针,而在 Java 中不需要?
- 为什么复制构造函数不需要检查输入对象是否指向自身?
- 为什么不需要在 C++20 中的依赖类型之前指定"typename"?
- 为什么 Mac 上不需要包含智能指针?
- 为什么MSVC(Visual C++)需要单独的dllimport和dllexport属性,而gcc不需要
- 我不明白为什么"Derived1"需要与"Derived3"相同的内存量
- 为什么在以下情况下不需要为依赖类型使用typename
- 为什么在调用C#DLL时不需要提供字符串缓冲区
- 为什么 pair 在初始化中不需要类型
- 为什么在VS2015中模板相关的嵌套类型名称中不需要typename关键字?
- 为什么在一个地方需要双倍英镑,而在这个宏观上不需要其他地方?
- 为什么嵌套类型的基类不需要"typename"?
- 为什么使用指向函数的指针调用虚函数时不需要指针"this"?
- 为什么我不需要在capnproto中使用AnyPointer::initAs?
- 如果不需要易失性,为什么 std::atomic 方法会提供易失性重载