我正在为我的库设计一个C++的异常层次结构."层次结构"是从std :: runtime_error派生的4个类.我想避免异常类的切片问题,因此使复制构造函数受到保护.但显然gcc需要在抛出它们的实例时调用复制构造函数,因此抱怨受保护的复制构造函数.Visual C++ 8.0编译相同的代码.是否有任何可移植的方法来解决异常类的切片问题?标准是否说明实现是否可以/应该要求抛出要抛出的类的复制构造函数?
块中的new表达式在我的计算机中try引发bad_alloc异常.
请注意,catch子句按值接收异常对象,而不是通过引用.e.what()打印"bad allocation"怎么样?我以为会被切成碎片.
#include <iostream>
int main()
{
try
{
int* p = new int[0x1F000000];
}
catch(std::exception e)
{
std::cout << e.what() << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud) 我有一个问题,我想复制一个对象,但希望避免切片.
DerivedObj derivedObj;
myFunc(derivedObj);
void myFunc(MyObj &obj)
{
MyObj *saveForLater = new MyObj(obj); // slices my object
// ... //
}
Run Code Online (Sandbox Code Playgroud)
有办法解决这个问题吗?我需要制作一份副本,因为原始对象在需要之前会留下范围.
我已经阅读了关于vtable的内容,并且已经理解了指向基类和派生类对象的基类指针的概念.有人可以解释当基类和派生类都是对象并且派生类对象被分配给基类对象时如何创建vtable的情况.以下示例中的案例3
#include <iostream>
#include <exception>
using namespace std;
class Base
{
public:
virtual void function1() { cout<<"Base - func1"<<endl; }
virtual void function2() { cout<<"Base - func2"<<endl; }
};
class Derived1: public Base
{
public:
virtual void function1() { cout<<"Derived1 - func1"<<endl; }
};
class Derived2: public Base
{
public:
virtual void function2() { cout<<"Derived2 - func2"<<endl; }
};
int main ()
{
// Case 1
Base* B1 = new Derived1();
B1->function1();
B1->function2();
// Case 2
cout<<endl;
Base* B2 = …Run Code Online (Sandbox Code Playgroud) C++ 专家兼 D 语言创始人Walter Bright表示:
切片问题很严重,因为它可能导致内存损坏,并且很难保证程序不会受到这种情况的影响。为了从语言中设计它,支持继承的类应该只能通过引用(而不是通过值)访问。D 编程语言具有这个特性。
如果有人通过给出一个 C++ 示例来解释它会更好,其中对象切片问题导致内存损坏?而这个问题用D语言是如何解决的呢?
我碰巧正在浏览 mongoDB 的源代码,发现了这个有趣的构造:
class NonspecificAssertionException final : public AssertionException {
public:
using AssertionException::AssertionException;
private:
void defineOnlyInFinalSubclassToPreventSlicing() final {}
};
Run Code Online (Sandbox Code Playgroud)
私有方法如何防止切片?我似乎想不出问题所在。
干杯,乔治
我读到了C++中的切片问题,我尝试了一些例子(我来自Java背景).不幸的是,我不明白一些行为.目前,我被困在这个例子中(来自Efficent C++第三版的替代例子).任何人都可以帮我理解吗?
我父母的简单类:
class Parent
{
public:
Parent(int type) { _type = type; }
virtual std::string getName() { return "Parent"; }
int getType() { return _type; }
private:
int _type;
};
Run Code Online (Sandbox Code Playgroud)
我简单的一个孩子:
class Child : public Parent
{
public:
Child(void) : Parent(2) {};
virtual std::string getName() { return "Child"; }
std::string extraString() { return "Child extra string"; }
};
Run Code Online (Sandbox Code Playgroud)
主要的:
void printNames(Parent p)
{
std::cout << "Name: " << p.getName() << std::endl;
if (p.getType() == 2)
{
Child & c …Run Code Online (Sandbox Code Playgroud) 这是代码:
#include <iostream>
#include <vector>
#include <array>
class Parent
{
public:
virtual void whatAmI(){std::cout << "A Parent" << std::endl;}
virtual long getValue(){std::cout << "value from Parent " << std::endl; return value;}
long value;
};
class Child : public Parent
{
public:
virtual void whatAmI(){std::cout << "A child" << std::endl;}
virtual long getValue(){std::cout << "value from Child " << std::endl; return value;}
long value;
};
class SomeClass
{
public:
Parent * parent;
};
int main()
{
Child c = Child();
SomeClass …Run Code Online (Sandbox Code Playgroud) 所以我对 C++ 感到耳目一新,老实说已经有一段时间了。我制作了一个控制台乒乓球游戏作为一种复习任务,并获得了一些关于使用多态性从我的类派生自基本“GameObject”(具有一些将对象绘制到屏幕的基本方法)的输入。
其中一个输入是(我后来问过)是从基类派生时内存是如何工作的。因为我并没有真正做过很多高级 C++。
例如,假设我们有一个基类,现在它只有一个“draw”方法(顺便说一句,为什么我们需要说它virtual?),因为所有其他派生对象实际上只共享一个公共方法,并且正在绘制:
class GameObject
{
public:
virtual void Draw( ) = 0;
};
Run Code Online (Sandbox Code Playgroud)
例如,我们还有一个球类:
class Ball : public GameObject
Run Code Online (Sandbox Code Playgroud)
我收到的输入是,在适当的游戏中,这些可能会保存在某种 GameObject 指针向量中。像这样的东西:std::vector<GameObject*> _gameObjects;
(所以是指向游戏对象的指针向量)(顺便说一句,为什么我们在这里使用指针?为什么不只是纯游戏对象?)。我们将使用以下内容实例化这些游戏对象之一:
_gameObjects.push_back( new Ball( -1, 1, boardWidth / 2, boardHeight / 2 ); );
Run Code Online (Sandbox Code Playgroud)
(new返回一个指向对象的指针是否正确?IIRC)。根据我的理解,如果我尝试执行以下操作:
Ball b;
GameObject g = b;
Run Code Online (Sandbox Code Playgroud)
事情会变得一团糟(如下所示:什么是对象切片?)
但是......当我这样做时,我不是简单地自己创建派生对象,new Ball( -1, 1, boardWidth / 2, boardHeight / 2 );还是自动将其分配为游戏对象?我真的无法弄清楚为什么一个有效而一个无效。例如,它是否与通过newvs创建对象Ball ball有关?
对不起,如果这个问题没有意义,我只是想了解这个对象切片是如何发生的。
在《C++ 编程语言》第 17.5.1.4 节中,有以下示例:
\nstruct Base {\n int b;\n Base(const Base&);\n};\n\nstruct Derived {\n int d;\n Derived(const Derived&);\n};\n\nvoid naive(Base* p) {\n B b2 = *p;\n};\n\nvoid user() {\n Derived d;\n naive(&d);\n Base bb = d;\n};\nRun Code Online (Sandbox Code Playgroud)\nI\xe2\x80\x99 省略了代码中的注释,并在naive() (应该是Base b2 ?) 中包含了明显的拼写错误。
我\xe2\x80\x99m 只是混淆了问题到底是什么:我没有理由期待一个Derived 在任何一种情况下都会复制 a 。我觉得好像我应该在这里遗漏一些东西,但我只是无法理解这个 \xe2\x80\x9cexample\xe2\x80\x9d 的意义。
c++ ×10
object-slicing ×10
inheritance ×2
d ×1
derived ×1
exception ×1
final ×1
gcc ×1
polymorphism ×1
virtual ×1