相关疑难解决方法(0)

学习C++:多态和切片

请考虑以下示例:

#include <iostream>
using namespace std;

class Animal
{
public:
    virtual void makeSound() {cout << "rawr" << endl;}
};

class Dog : public Animal
{
public:
    virtual void makeSound() {cout << "bark" << endl;}
};

int main()
{
    Animal animal;
    animal.makeSound();

    Dog dog;
    dog.makeSound();

    Animal badDog = Dog();
    badDog.makeSound();

    Animal* goodDog = new Dog();
    goodDog->makeSound();
}
Run Code Online (Sandbox Code Playgroud)

输出是:

rawr
bark
rawr
bark
Run Code Online (Sandbox Code Playgroud)

但我认为产量肯定应该是"粗树皮树皮".badDog有什么用?


更新:您可能对我的另一个问题感兴趣.

c++ polymorphism

54
推荐指数
2
解决办法
7083
查看次数

子类/继承标准容器?

我经常在Stack Overflow上阅读这些语句.就个人而言,我没有发现任何问题,除非我以多态方式使用它; 即我必须使用virtual析构函数.

如果我想扩展/添加标准容器的功能那么什么是比继承一个更好的方法?将这些容器包装在自定义类中需要更多的努力并且仍然是不洁净的.

c++ inheritance standard-library

48
推荐指数
5
解决办法
2万
查看次数

在C++编译期间,"具有虚拟方法......但非虚拟析构函数"警告意味着什么?

#include <iostream>
using namespace std;

class CPolygon {
  protected:
    int width, height;
  public:
    virtual int area ()
      { return (0); }
  };

class CRectangle: public CPolygon {
  public:
    int area () { return (width * height); }
  };
Run Code Online (Sandbox Code Playgroud)

有汇编警告

Class '[C@1a9e0f7' has virtual method 'area' but non-virtual destructor
Run Code Online (Sandbox Code Playgroud)

如何理解这个警告以及如何改进代码?

[编辑]这个版本现在正确吗?(试图回答用这个概念来阐明自己)

#include <iostream>
using namespace std;

class CPolygon {
  protected:
    int width, height;
  public:
    virtual ~CPolygon(){};
    virtual int area ()
      { return (0); }
  };

class CRectangle: public CPolygon {
  public: …
Run Code Online (Sandbox Code Playgroud)

c++ polymorphism virtual

39
推荐指数
2
解决办法
4万
查看次数

嵌套try-catch中的ex.what()更改

我有一个嵌套的try-catch代码,如下所示:

void A()
{
    try
    {
        //Code like A = string(NULL) that throws an exception
    }
    catch(std::exception& ex)
    {
        cout<<"in A : " << ex.what();
        throw ex;
    }
}

void B()
{
   try
   {
       A();
   }
   catch(std::exception& ex)
   {
       cout<<"in B : " << ex.what();
   }
}
Run Code Online (Sandbox Code Playgroud)

运行后我得到了这个结果:

in A: basic_string::_M_construct null not valid
in B: std::exception
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,ex.what()在函数A中正常工作并告诉我正确的描述,但在B中ex.what()告诉我std::exception.为什么会这样?

我在函数A的catch子句中抛出了不同或错误的东西吗?如何抛出嵌套异常以便我可以在B中获得确切的异常描述?

c++ exception-handling try-catch

29
推荐指数
3
解决办法
1946
查看次数

这应该被称为对象切片的一些特殊情况吗?

比方说,我有一个类Derived从类派生Basesizeof(Derived) > sizeof(Base).现在,如果分配一个这样的数组Derived:

Base * myArray = new Derived[42];
Run Code Online (Sandbox Code Playgroud)

然后尝试使用访问n-th对象

doSomethingWithBase(myArray[n]);
Run Code Online (Sandbox Code Playgroud)

然后,由于Base从无效位置访问,这可能(但不总是)导致未定义的行为.

这种编程错误的正确术语是什么?它应该被视为对象切片的情况吗?

c++ arrays inheritance terminology pointer-arithmetic

25
推荐指数
4
解决办法
1391
查看次数

C++转换运算符重载和多态

我对C++的这种行为感到困惑:

struct A {
   virtual void print() const { printf("a\n"); }
};

struct B : public A {
   virtual void print() const { printf("b\n"); }
};

struct C {
   operator B() { return B(); }
};

void print(const A& a) {
   a.print();
}

int main() {
   C c;
   print(c);
}
Run Code Online (Sandbox Code Playgroud)

那么,测验是,程序的输出是什么 - a或b?嗯,答案是答案.但为什么?

c++ polymorphism casting overloading operator-keyword

22
推荐指数
1
解决办法
1080
查看次数

gcc4.9.2的std :: vector的libstdc ++实现继承自_Vector_base(非虚拟目标).为什么这样好?

所以我一直在使用从std :: vector派生的容器.也许这是一个糟糕的设计决定,原因有几个,而且你是否应该做这样的事情的问题在这里有广泛的讨论:

你不能继承std :: vector

子类/继承标准容器?

从C++ STL容器中获取是否存在任何真正的风险?

是否可以从STL容器继承实现,而不是委托?

我确信我已经错过了一些讨论......但是在链接中找到了两个观点的合理论据.据我所知,"因为~vector()是非虚拟的"是你不应该从stl容器继承的"规则"的基础.但是,如果我在g ++ 4.9.2中查看std :: vector的实现,我发现std :: vector继承自_Vector_base,而_Vector_base是非虚拟析构函数.

template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
class vector : protected _Vector_base<_Tp, _Alloc>
{
...
  ~vector() _GLIBCXX_NOEXCEPT
  { std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
    _M_get_Tp_allocator()); }

...
}
Run Code Online (Sandbox Code Playgroud)

哪里:

template<typename _Tp, typename _Alloc>
struct _Vector_base
{
...
  ~_Vector_base() _GLIBCXX_NOEXCEPT
  { _M_deallocate(this->_M_impl._M_start, this->_M_impl._M_end_of_storage
    - this->_M_impl._M_start); }

...
}
Run Code Online (Sandbox Code Playgroud)

所以std :: vector的gcc 4.9.2实现继承自带有非虚析构函数的基类.这让我相信这是一种可接受的做法.为什么这样好?这种做法没有危险的具体条件是什么?

c++ inheritance vector libstdc++

17
推荐指数
1
解决办法
1039
查看次数

boost :: checked_delete的目的

我不明白boost :: checked_delete的目的.文件说:

在5.3.5/5中,C++标准允许使用delete-expression删除指向不完整类类型的指针.当类具有非平凡的析构函数或类特定的运算符delete时,行为是未定义的.有些编译器会在删除不完整的类型时发出警告,但不幸的是,并非所有编译器都会发出警告,程序员有时会忽略或禁用警告.

提供的函数和类模板可用于防止这些问题,因为它们需要完整的类型,否则会导致编译错误.

因此,C++标准允许您删除不完整的类型,如果类型具有非平凡的析构函数,则会导致未定义的行为.什么?一个不完整的类型怎么可能有任何析构函数?不完整的类型只是原型吗?

c++ standards boost

16
推荐指数
1
解决办法
3965
查看次数

为什么从一个具体的类派生出来是一个糟糕的设计

我正在阅读有关非虚拟接口模式的内容:Herb Sutter正在讨论为什么虚拟功能在大多数情况下必须是私有的,在某些情况下受到保护而从不公开.

但在文章的最后他写道:

不要来自具体的课程.或者,正如Scott Meyers在更有效的C++第33项中所述,[8]"使非叶类抽象化".(不可否认,它可能在实践中发生 - 在其他人编写的代码中,当然不是由您自己编写! - 在这种情况下,您可能必须拥有一个公共虚拟析构函数,以适应已经很糟糕的设计.更好地重构但是,如果可以的话,修复设计.)

但我不明白为什么这是一个糟糕的设计

c++ inheritance

16
推荐指数
4
解决办法
3219
查看次数

对象切片是否有用?

当我们将派生类的对象分配或复制到其基类的对象时,会发生对象切片,从而在该过程中丢失它的派生部分.

这里有更深入的解释:C++中的切片问题是什么?.

(我自己,我不认为它是一个问题,而是语言价值语义的自然结果,但这不是这个问题的重点.)

我想知道的是:有没有你有意使用它的情况?这是一个"工作的正确工具"吗?

c++ inheritance object-slicing

15
推荐指数
1
解决办法
633
查看次数