防止切片的惯用方法? 有时候,C++默认允许切片是一个烦人的问题。比如说 struct foo { int a; }; struct bar : foo { int b; }; int main() { bar x{1,2}; foo y = x; // <- I dont want this to compile! } structfoo{inta;}; 结构条:foo{intb;}; int main(){ 条x{1,2}; foo y=x;//

防止切片的惯用方法? 有时候,C++默认允许切片是一个烦人的问题。比如说 struct foo { int a; }; struct bar : foo { int b; }; int main() { bar x{1,2}; foo y = x; // <- I dont want this to compile! } structfoo{inta;}; 结构条:foo{intb;}; int main(){ 条x{1,2}; foo y=x;//,c++,inheritance,object-slicing,C++,Inheritance,Object Slicing,通过声明复制构造函数受保护,可以防止基类被复制到派生类的成员函数之外以及基类本身: struct foo { // ... protected: foo(foo&) = default; }; 我不确定是否有命名的习惯用法,但您可以向重载集中添加一个已删除的函数,该函数比基类切片操作更匹配 struct foo { int a; foo() = default; // you have to add this because of the temp

通过声明复制构造函数受保护,可以防止基类被复制到派生类的成员函数之外以及基类本身:

struct foo {
    // ...
protected:
    foo(foo&) = default;
};

我不确定是否有命名的习惯用法,但您可以向重载集中添加一个已删除的函数,该函数比基类切片操作更匹配

struct foo 
{ 
    int a; 
    foo() = default; // you have to add this because of the template constructor

    template<typename T>
    foo(const T&) = delete; // error trying to copy anything but a foo

    template<typename T>
    foo& operator=(const T&) = delete; // error assigning anything else but a foo
};
structfoo
{ 
INTA;
foo()=default;//由于模板构造函数的原因,您必须添加它
模板
foo(const T&)=delete;//尝试复制除foo以外的任何内容时出错
模板
foo&operator=(const T&)=delete;//分配除foo以外的任何内容时出错
};

然后,您只能复制构造或将
foo
复制分配给
foo
。任何其他类型都会选择函数模板,您将在使用已删除函数时出错。这意味着您的类以及使用它的类不再是聚合。因为添加的成员是模板,所以它们不被视为复制构造函数或复制赋值运算符,因此您将获得默认的复制和移动构造函数和赋值运算符。

自2011年以来,惯用的方法一直是使用
自动

#include <iostream>
struct foo { int a; };
struct bar : foo { int b; };

int main() {
    bar x{1,2};
    auto y = x; // <- y is a bar
}
#包括
结构foo{int a;};
结构条:foo{intb;};
int main(){
条x{1,2};

自动y=x;//但是我不能再复制
foo
s了:(如果可能的话,我想阻止只将一个条复制到一个foo,但这不会阻止像这样的显式切片:
foo y=static\u cast(x)
。也就是说,可能操作不是问题。如果我理解正确,这是防止函数参数在general@user463035818.我一直在使用它,因为我问了这个问题。我把它看作是反向SFINAE。你做了你想编译的重载,然后添加一个删除的模板,每停止一次还有一件事。事实上,我有点急于接受这个答案。这项技术很棒,但事实上它为专门处理各种不需要的任务打开了大门,尽管如果我不得不在爪哇语的“不惜一切代价防止一切可能的愚蠢”和蟒蛇语的“我们都是成年人”之间做出选择,那么我知道该选什么;)最简单的方法是不使用继承。您必须将
foo
作为
bar
@KevinZ的成员变量
#include <iostream>

struct foo { int a; };
struct bar 
{ 
    bar(int a, int b)
    : foo_(a)
    , b(b)
    {}

    int b; 

    int get_a() const { return foo_.a; }

private:
    foo foo_;
};

int main() {
    bar x{1,2};
//    foo y = x; // <- does not compile

}
#include <iostream>

struct foo { 
    int a; 
protected:
    foo(foo const&) = default;
    foo(foo&&) = default;
    foo& operator=(foo const&) = default;
    foo& operator=(foo&&) = default;

};

struct bar : foo
{ 
    bar(int a, int b) 
    : foo{a}, b{b}
    {}

    int b; 
};

int main() {
    auto x  = bar (1,2);
//    foo y = x; // <- does not compile
}