假设以下布局:
class Base
{
protected:
Base(P1 p1, P2 p2, P3 p3);
public:
virtual void SomeMethod() = 0;
}
class Derived : public Base
{
public:
using Base::Base;
public:
virtual void SomeMethod() override;
};
Run Code Online (Sandbox Code Playgroud)
我应该能够在Derived这里指定公共构造函数吗?VC++给出以下错误:
无法访问类'Derived'中声明的受保护成员
编译器已在此处生成'Derived :: Derived'[指向使用Base :: Base行]
请参阅'Derived'的声明
即它忽略了继承构造函数上方的访问修饰符.
这是该功能的限制吗?Base对于具有公共构造函数的类没有任何意义,因为它永远不能直接实例化(由于纯虚方法).
在这个例子中:
template<class T>
struct S : T
{
using T::X;
};
Run Code Online (Sandbox Code Playgroud)
T::X是指部件上的从属名称X在T.如果S<T>实例化为T = X:
struct X
{
X(int) {}
};
...
S<X> s(42);
Run Code Online (Sandbox Code Playgroud)
using声明是否会成为继承构造函数?
Clang拒绝代码DEMO,而g ++接受它.
请注意,如果我们写:
using T::X::X;
Run Code Online (Sandbox Code Playgroud)
两个编译器都接受代码并将其视为继承构造函数.被using T::X允许通过标准成为继承,构造函数?
c++ templates using-declaration language-lawyer inheriting-constructors
我在我的项目中遇到以下错误:
error: use of deleted function ‘C::C(int)’ note: ‘C::C(int)’ is implicitly deleted because the default definition would be ill-formed: error: use of deleted function ‘M::M()’
这是我正在使用的代码:
struct M {
M(int){}
M() = delete; // Allowing this would work.
};
struct B {
B(int) {}
B() = delete;
};
struct C : public B {
using B::B;
M n = {5};
// C(int i) : B(i) {} // Adding this would work
};
C c{1};
Run Code Online (Sandbox Code Playgroud)
有谁知道为什么会这样?
很明显,语言愿意在继承的构造函数的末尾添加更多的初始化(因为它愿意调用默认的构造函数).显然,它愿意隐式地将对非默认构造函数(类初始化)的调用添加到显式定义的构造函数的末尾.但由于某种原因,我不明白,它不愿意同时做这两件事.
根据这个问题,完美转发不够完美,不应该在这里使用.
注意:在实际情况下,构造函数 …
我试图创建一个派生自的类,boost::multiprecision::mpz_int并让它继承基类构造函数:
#include <boost/multiprecision/gmp.hpp>
using namespace boost::multiprecision;
struct Integer:
mpz_int
{
using mpz_int::mpz_int;
};
Run Code Online (Sandbox Code Playgroud)
g ++ 4.9.0给出了以下错误:
main.cpp:8:20: error: 'template<class tag, class Arg1, class Arg2, class Arg3, class Arg4> Integer::Integer(const boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>&)' inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'
using mpz_int::mpz_int;
^
main.cpp:8:20: error: conflicts with version inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'
main.cpp:8:20: error: 'template<class Other, boost::multiprecision::expression_template_option ET> Integer::Integer(const boost::multiprecision::number<Backend, ExpressionTemplates>&)' inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'
main.cpp:8:20: error: conflicts with version inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'
main.cpp:8:20: error: 'template<class Other, boost::multiprecision::expression_template_option ET> Integer::Integer(const boost::multiprecision::number<Backend, …Run Code Online (Sandbox Code Playgroud) 在阅读这个问题时,我发现了一个奇怪的观点:
template <typename T>
class Subclass : public Baseclass<T>
{
public:
using typename Baseclass<T>::Baseclass;
// ^^^^^^^^
};
Run Code Online (Sandbox Code Playgroud)
既然typename,Baseclass<T>::Baseclass应该注入类名,而不是构造函数.据我所知,情况与此相同:
template <typename T>
class Base
{
public:
typedef short some_type;
};
template <typename T>
class Sub : public Base<T>
{
public:
using typename Base<T>::some_type;
};
Run Code Online (Sandbox Code Playgroud)
为了确保,我写了一个测试代码.
#include <iostream>
template <typename T>
class Base
{
public:
Base() { std::cout << "A::A()\n"; }
Base(int) { std::cout << "A::A(int)\n"; }
Base(const char *) { std::cout << "A::A(const …Run Code Online (Sandbox Code Playgroud) c++ typename using-declaration language-lawyer inheriting-constructors
我不确定这是GCC编译器的错误还是预期的行为noexcept.
请考虑以下示例:
struct B {
B(int) noexcept { }
virtual void f() = 0;
};
struct D: public B {
using B::B;
D() noexcept(noexcept(D{42})): B{42} { }
void f() override { }
};
int main() {
B *b = new D{};
}
Run Code Online (Sandbox Code Playgroud)
如果noexcept删除它,它编译.
无论如何,正如在例子中,我从GCC v5.3.1得到了这个错误:
test.cpp:8:31: error: invalid use of incomplete type ‘struct D’
D() noexcept(noexcept(D{42})): B{42} { }
^
Run Code Online (Sandbox Code Playgroud)
据我所知,struct D不是一个不完整的类型,但继承构造函数涉及到语句,看起来编译器实际上考虑的是基本结构的完整性而B不是D.
这是预期的行为还是合法代码?
为清楚起见:
这个故事与我之前的问题类似.支持C++ 11的所有GCC版本都具有这种确切的行为.我找不到任何其他编译器与我的测试用例斗争.
测试用例:
struct BaseFooWrapper
{
BaseFooWrapper(int qux)
{ }
};
struct Foo
{
Foo(BaseFooWrapper & foo)
: foo(foo)
{ }
BaseFooWrapper & foo;
};
struct SomeFooWrapper : public BaseFooWrapper
{
using BaseFooWrapper::BaseFooWrapper;
Foo foo{*this};
};
int main()
{
SomeFooWrapper wrapped_foo(1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这段代码用clang(3.4到4.0),icc(16,17),Visual C++(19.00.23506)编译.
如果我用手写版本替换构造函数继承,那么GCC开始编译代码:
struct BaseFooWrapper
{
BaseFooWrapper(int qux)
{ }
};
struct Foo
{
Foo(BaseFooWrapper & foo)
: foo(foo)
{ }
BaseFooWrapper …Run Code Online (Sandbox Code Playgroud) 我即将创建一个异常类层次结构,概念上看起来像这样:
#include <iostream>
#include <stdexcept>
class ExceptionBase : public std::runtime_error {
public:
ExceptionBase( const char * msg ) : std::runtime_error(msg) {}
};
class OperationFailure : virtual public ExceptionBase {
public:
using ExceptionBase::ExceptionBase;
};
class FileDoesNotExistError : virtual public ExceptionBase {
public:
using ExceptionBase::ExceptionBase;
};
class OperationFailedBecauseFileDoesNotExistError
: public OperationFailure, FileDoesNotExistError {
public:
using ExceptionBase::ExceptionBase; // does not compile
};
int main() {
OperationFailedBecauseFileDoesNotExistError e("Hello world!\n");
std::cout << e.what();
}
Run Code Online (Sandbox Code Playgroud)
所有构造函数应该与ExceptionBase类的构造函数相同.派生的异常仅在类型上有所不同,否则没有添加的功能.上面代码中提到的最后一个异常类型也应该有这些构造函数.这是否可以使用C++ 11标准的继承构造函数功能?如果那是不可能的:还有什么选择?
(顺便说一句:在上面的代码中的类OperationFailure和FileDoesNotExistError.没有用gcc 4.8编译,但铿锵3.4显然,海湾合作委员会拒绝为虚拟基础继承构造函数这将是有趣的,知道谁在这里两种编译器拒绝了类OperationFailedBecauseFileDoesNotExistError …
考虑:
struct B {
void f();
private:
B(int, int = 0);
};
struct D : B { using B::B; };
void B::f() {
auto a = D{0};
auto b = D(0);
auto c = D(0, 0);
D x{0};
D y(0);
D z(0, 0);
}
Run Code Online (Sandbox Code Playgroud)
GCC 接受(从 7.1 开始;以前拒绝所有)。Clang 接受bandxyz但拒绝aand c。MSVC 在 C++14 模式下拒绝所有,但在 C++17 模式下接受所有。
哪些编译器是正确的?C++14 和 C++17 之间的规则是否发生了变化——如果是这样,为什么在 C++14 中B::f不允许访问它自己的构造函数(命名为 via D)?为什么 Clang 只接受(函数式)强制转换 atb而不是列表初始化 at …
在这里我发现:
默认情况下,继承构造函数都是noexcept(true),除非它们需要调用noexcept(false)函数,在这种情况下这些函数是noexcept(false).
这是否意味着在下面的示例中,继承的构造函数是noexcept(true),即使它已经noexcept(false)在基类中显式定义,或者它被认为是一个函数是noexcept(false)被调用?
struct Base {
Base() noexcept(false) { }
};
struct Derived: public Base {
using Base::Base;
};
int main() {
Derived d;
}
Run Code Online (Sandbox Code Playgroud) 请参见以下代码:
struct base {};
template <class T>
struct derived : T {
using base_type = T;
using base_type::T;
};
int main()
{
derived<base> x;
}
Run Code Online (Sandbox Code Playgroud)
GCC接受此代码,但是Clang和MSVC拒绝它。谁是正确的,为什么?
每当在任何派生类中调用任何构造函数时,任务只能通过最终隐式或显式地调用基类构造函数来完成(如果我在这里错了,请纠正我).
因为我们打算创建派生类的实例,但是因为最后调用了基类构造函数.
那么,尽管调用了基类的构造函数,如何构造派生类的实例?