C++ 为什么禁止建造峡湾?
下面是一些代码:C++ 为什么禁止建造峡湾?,c++,C++,下面是一些代码: #包括 #包括 #包括 #包括 #包括 #包括 甲级{ int*m; std::istream in; (int*m,std::string file):m{m},在{std::ifstream{file}}{foo();} 公众: A(int*m):m{m},在{std::cin}{foo();} void foo(){} }; int main(){ 返回0; } 当我尝试执行g++-std=c++14 main.cc时,最终得到的结果是: $ g++ -std=c++1
#包括
#包括
#包括
#包括
#包括
#包括
甲级{
int*m;
std::istream in;
(int*m,std::string file):m{m},在{std::ifstream{file}}{foo();}
公众:
A(int*m):m{m},在{std::cin}{foo();}
void foo(){}
};
int main(){
返回0;
}
当我尝试执行g++-std=c++14 main.cc
时,最终得到的结果是:
$ g++ -std=c++14 main.cc
main.cc: In constructor ‘A::A(int*, std::__cxx11::string)’:
main.cc:11:62: error: ‘std::basic_istream<_CharT, _Traits>::basic_istream(std::basic_istream<_CharT, _Traits>&&) [with _CharT = char; _Traits = std::char_traits<char>]’ is protected within this context
A(int *m, std::string file): m{m}, in{std::ifstream{file}} { foo(); }
^
In file included from /usr/include/c++/7/iostream:40:0,
from main.cc:1:
/usr/include/c++/7/istream:613:7: note: declared protected here
basic_istream(basic_istream&& __rhs)
^~~~~~~~~~~~~
main.cc: In constructor ‘A::A(int*)’:
main.cc:13:33: error: ‘std::basic_istream<_CharT, _Traits>::basic_istream(const std::basic_istream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]’ is protected within this context
A(int *m): m{m}, in{std::cin} { foo(); }
^
In file included from /usr/include/c++/7/iostream:40:0,
from main.cc:1:
/usr/include/c++/7/istream:611:7: note: declared protected here
basic_istream(const basic_istream&) = delete;
^~~~~~~~~~~~~
main.cc:13:33: error: use of deleted function ‘std::basic_istream<_CharT, _Traits>::basic_istream(const std::basic_istream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]’
A(int *m): m{m}, in{std::cin} { foo(); }
^
In file included from /usr/include/c++/7/iostream:40:0,
from main.cc:1:
/usr/include/c++/7/istream:611:7: note: declared here
basic_istream(const basic_istream&) = delete;
^~~~~~~~~~~~~
这是为什么?您需要决定
A
是否应该拥有流
如果它确实拥有流,那么您不能传递它std::cin
,您需要直接存储ifstream
,或者存储unique\u ptr
,而不是istream
,因为您希望允许派生类型,例如ifstream
如果它是非拥有的,则无法在构造函数中创建实例。相反,调用方需要创建并拥有流,并将对它的引用传递给构造函数。为此,如果要允许类的赋值或原始(非拥有)指针istream*
,则应保存引用istream&
,而不是istream
或std::reference\u wrapper
如果希望两者都允许,可以创建一个只接受引用的基类,然后创建一个派生类来额外构造和拥有流。然后,无论何时需要,您都可以根据是否应该拥有派生类或基类类型来构造它
class A {
std::istream& in;
public:
A() : A(std::cin) { }
A(std::istream& in): in(in) { }
};
class B : public A {
std::ifstream ifs;
public:
B(std::string file) : A(ifs), ifs(file) { }
};
如果要使用具有运行时多态性的两个类,可能需要通过提供一个虚拟析构函数和虚拟成员函数使类具有多态性
或者,您可以为一个拥有版本和一个非拥有版本的类创建模板。或者您可以使用
std::variant
作为成员,它可以保存拥有或不拥有的类型。在您的情况下,哪种解决方案是最好的,取决于您打算如何使用该类。您需要决定A
是否应该拥有该流
如果它确实拥有流,那么您不能传递它std::cin
,您需要直接存储ifstream
,或者存储unique\u ptr
,而不是istream
,因为您希望允许派生类型,例如ifstream
如果它是非拥有的,则无法在构造函数中创建实例。相反,调用方需要创建并拥有流,并将对它的引用传递给构造函数。为此,如果要允许类的赋值或原始(非拥有)指针istream*
,则应保存引用istream&
,而不是istream
或std::reference\u wrapper
如果希望两者都允许,可以创建一个只接受引用的基类,然后创建一个派生类来额外构造和拥有流。然后,无论何时需要,您都可以根据是否应该拥有派生类或基类类型来构造它
class A {
std::istream& in;
public:
A() : A(std::cin) { }
A(std::istream& in): in(in) { }
};
class B : public A {
std::ifstream ifs;
public:
B(std::string file) : A(ifs), ifs(file) { }
};
如果要使用具有运行时多态性的两个类,可能需要通过提供一个虚拟析构函数和虚拟成员函数使类具有多态性
或者,您可以为一个拥有版本和一个非拥有版本的类创建模板。或者您可以使用
std::variant
作为成员,它可以保存拥有或不拥有的类型。在您的情况下,哪种解决方案是最好的,取决于您打算如何使用该类。您不能复制cin
,但可以存储对它的引用。只需将中的作为一个引用,它就会解决这个问题。但是,看到您的编辑,将临时引用绑定到非常量引用时会出现问题。@iz_uu;Ok,执行此操作:const std::istream&in
使其可编译,但使其常量
会丢失任何东西吗?因为我们永远不会分配给istream
,这不是很好吗?从流中读取,就是对它进行变异const
将使其无法读取流。@iz_u有一个优雅的解决方案吗?你如何阅读它,并将其作为成员(拥有它)?胡桃木下面的解决方案在我看来很好。你不能复制cin
,但你可以存储对它的引用。只需将中的作为一个引用,它就会解决这个问题。但是,看到您的编辑,将临时引用绑定到非常量引用时会出现问题。@iz_uu;Ok,执行此操作:const std::istream&in
使其可编译,但使其常量
会丢失任何东西吗?因为我们永远不会分配给istream
,这不是很好吗?从流中读取,就是对它进行变异const
将使其无法读取流。@iz_u有一个优雅的解决方案吗?你如何能从中阅读,并将其作为一个成员(拥有它)?胡桃木下面的解决方案对我来说很好。在我的特殊情况下,我没有任何继承或多态性。A
是否可能以某种方式从
中的读取,其中
中的可以是std::cin
或动态构造的ifstream
?目前唯一可能解决这个问题的方法似乎是将ifs
作为A
的附加成员,然后在中构造时,我们在(ifs)
中执行。这看起来有点多余。@herophant是的,您当然可以合并这两个类,并拥有一个引用和非引用成员,或者您可以使用std::variant
,但是使用std::variant
有点棘手,可能不值得。类模板可以使类型之间的切换变得很容易。同样,我不知道具体的需求是什么。在我的特殊情况下,我没有任何继承或多态性。A
是否可能以某种方式从
中的读取,其中
中的可以是s