小编cur*_*guy的帖子

如果虚函数没有实现,大多数派生类都无法编译,但如果一个基类没有实现虚函数,则可以编译

我有一个包含4个类的C++程序:Person,Student,Employee和PartTimeStudent.

Student和Employee都派生自Person,而PartTimeStudent派生自所有3个类(使其成为派生程度最高的类).Person,Student和Employee也有一个名为VDescribe()的派生函数.

请参阅以下代码:

class Person
{
    ...    
    virtual void VDescribe();
    ...
};

class Student : virtual public Person
{
    ...    
    virtual void VDescribe();
    ...
};

class Employee : virtual public Person
{
    ...    
    virtual void VDescribe();
    ...
};

class PartTimeStudent : virtual public Person,
    virtual public Student,
    virtual public Employee
{
    ...
};
Run Code Online (Sandbox Code Playgroud)

注意:在上面的代码片段中,我省略了构造函数,析构函数和成员变量,因为它们与手头的问题无关.

当我尝试编译代码时,我收到以下错误:

override of virtual function "Person::VDescribe" is ambiguous

'PartTimeStudent': ambiguous inheritance of 'void Person::VDescrive(void)'

'PartTimeStudent': ambiguous inheritance of 'void Person::VDescribe(void)'
Run Code Online (Sandbox Code Playgroud)

但是,仅当Student和Employee都实现VDescribe()时才会出现这种情况.如果其中一个类未实现VDescribe(),则编译成功.我仍然会收到警告,例如,如果我从Employee中省略VDescribe(),则会出现以下警告:

'PartTimeStudent': inherits 'Student::Student::VDescribe' via dominance …
Run Code Online (Sandbox Code Playgroud)

c++ overriding virtual-functions multiple-inheritance virtual-inheritance

2
推荐指数
1
解决办法
113
查看次数

使用`dynamic_cast`时c ++底漆是否有问题?

引自C++ Primer 5th 19.2.1.dynamic_cast运算符

dynamic_cast具有以下形式:

dynamic_cast<type*>(e)
dynamic_cast<type&>(e)
dynamic_cast<type&&>(e)
Run Code Online (Sandbox Code Playgroud)

其中type必须是类类型,并且(通常)命名具有虚函数的类.在第一种情况下,e必须是有效的指针(第2.3.2节,第52页); 在第二,e 必须是左值; 而在第三,e不能是左值.

在所有情况下,类型e必须是从目标类型公开派生的类类型,目标类型的公共基类,或者与目标类型相同.如果e有这些类型之一,那么演员表会成功.否则,演员表失败.
如果指针类型的dynamic_cast失败,则结果为0.如果对引用类型的dynamic_cast失败,则运算符抛出类型异常bad_cast

但是,我在这里写了一段代码片段:

struct A {};
struct B : private A // note: *private* inheritance
{
  A* test() {
    return dynamic_cast<A*>(this);
  }
};

int main()
{
  B b;
  if(b.test()==nullptr)
      throw 1;
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码片段中,A它只是一个私有基础B,c ++入门没有考虑到它.但是,此代码段可以编译并运行而不会出错.底漆有错吗?

c++ dynamic-cast access-control private-inheritance

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

作为函数参数的"指向寄存器变量的指针"有什么作用?

据我所知,register说明符提示编译器将变量存储在寄存器中.这一切都很好,直到我XKBlib.h从Xorg-7.7中看到以下声明:

extern  int     XkbTranslateKeySym(
    Display *           /* dpy */,
    register KeySym *       /* sym_return */,
    unsigned int        /* modifiers */,
    char *          /* buffer */,
    int             /* nbytes */,
    int *           /* extra_rtrn */
);
Run Code Online (Sandbox Code Playgroud)

注意如何sym_return作为指向寄存器变量指针传递.是什么让我想知道的是

  1. 这似乎是允许的,尽管无法获取寄存器变量的地址,
  2. 这在某种程度上似乎很重要,可以在函数声明中提到.

点1似乎在某种程度上是无效的,因为我似乎能够将指针传递给非register变量,即使-pedantic-errors是GCC的标志.

那么,与带有省略register关键字的声明相比,这个声明有什么变化呢?它会改变召唤惯例还是什么?

c function calling-convention function-declaration register-keyword

2
推荐指数
1
解决办法
191
查看次数

make_unique 不会编译用于创建单例实例

全部,

我正在使用 C++14,并且正在制作一个或多或少的标准单例。我正在使用最新的 Visual Studio 2017。此代码有效:

#include <memory>
class A
{
public:
  static A& getInstance()
  {
    if (instance == nullptr)
      instance = std::unique_ptr<A>(new A());
    return *instance;
  }

private:
  A() {}
  static std::unique_ptr<A> instance;
};
std::unique_ptr<A> A::instance = nullptr;
Run Code Online (Sandbox Code Playgroud)

但是,当我将单例实例的创建更改为:

instance = std::make_unique<A>();
Run Code Online (Sandbox Code Playgroud)

我在尝试访问私有成员时收到编译错误:

Error   C2248   'A::A': cannot access private member declared in class 'A'      
c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.14.26428\include\memory   2510    
Run Code Online (Sandbox Code Playgroud)

这对我来说感觉像是一个错误,因为这两种形式在功能上应该是相同的?想法?

c++ singleton private-constructor unique-ptr c++14

2
推荐指数
1
解决办法
4751
查看次数

静态选择的功能和虚拟功能

最近我看到了这个C++标准段落(http://eel.is/c++draft/expr.post#expr.call-5):

如果postfix-expression指定析构函数,则函数调用表达式的类型为void; 否则,函数调用表达式的类型是静态选择函数的返回类型(即,忽略虚拟关键字),即使实际调用的函数的类型不同.此返回类型应为对象类型,引用类型或cv void.

我真的不明白这一部分:

函数调用表达式的类型是静态选择函数的返回类型(即,忽略虚拟关键字),即使实际调用的函数的类型不同.

  1. 这里静态选择的功能是什么?
  2. 虚拟功能如何静态选择?我一直以为它是在运行时选择的.
  3. 即使实际调用的函数类型不同.

调用表达式如何实际调用所选择的不同类型的函数?

c++ virtual-functions static-typing language-lawyer covariant-return-types

2
推荐指数
1
解决办法
77
查看次数

为什么在没有body的情况下调用纯虚方法不会导致链接器错误?

我今天遇到了相当奇怪的情况.在Interface构造函数中直接调用纯虚方法时,我得到一个未定义的引用错误.

class Interface
{
public:    
    virtual void fun() const = 0; 
    Interface(){ fun(); }
};

class A : public Interface
{
public:
    void fun() const override {};
};

int main()
{
    A a;
}
Run Code Online (Sandbox Code Playgroud)

结果是:

prog.cc: In constructor 'Interface::Interface()':
prog.cc:5:22: warning: pure virtual 'virtual void Interface::fun() const' called from constructor
5 |     Interface(){ fun(); }
  |                      ^
/tmp/ccWMVIWG.o: In function `main':
prog.cc:(.text.startup+0x13): undefined reference to `Interface::fun() const'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

但是,使用不同的方法将fun()调用包装为:

class Interface
{
public:    
    virtual …
Run Code Online (Sandbox Code Playgroud)

c++ constructor virtual-functions pure-virtual undefined-behavior

2
推荐指数
1
解决办法
94
查看次数

关于shared_ptr引用计数块

我有两个关于std::shared_ptr控制块的问题:

(1)关于大小:我如何以编程方式找到控制块的确切大小std::shared_ptr

(2)关于逻辑:另外,boost::shared_ptr提到它们在控制块的变化方面是完全无锁的.(从Boost版本1.33.0开始,shared_ptr在大多数常见平台上使用无锁实现.)我没有想一想std::shared_ptr- 是否计划用于任何未来的C++版本?这不也意味着boost::shared_ptr多线程案例更好吗?

c++ multithreading lock-free shared-ptr c++11

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

虚拟constexpr函数怎么可能?

从C ++ 2a开始,虚拟函数现在可以是constexpr。但是据我所知,您仍然不能在constexpr上下文中调用任意函数指针。

动态多态通常使用vtable来实现,其中包含要调用的函数指针。

另外,动态多态性virtual对于调用您不知道在编译时是哪个类型的重写函数很有用。例如:

struct A {
    virtual void fn() const {
        std::cout << 'A' << std::endl;
    }
};

void a_or_b(A const& a) {
    // The compiler has no idea `B` exists
    // it must be deferred at runtime
    a.fn();
}

struct B : A {
    void fn() const override {
        std::cout << 'A' << std::endl;
    }
};

int main() {
    // We choose which class is sent
    a_or_b(rand() % 2 ? A{} : B{});
}
Run Code Online (Sandbox Code Playgroud)

因此,考虑到那些在编译时无法调用函数指针并且在编译器没有足够的信息来静态地推断要调用的函数时使用了虚拟多态性的方法,虚拟constexpr函数怎么可能?

c++ virtual-functions function-pointers constexpr c++20

2
推荐指数
1
解决办法
197
查看次数

atomic_load() 和赋值有什么区别?

我正在开发一个处理大量原子操作的项目。到目前为止,我还不知道\xe2\x80\x99t atomic_load(),并且仅依靠赋值运算符来获取原子类型的值,并且除了这么多测试之外,我还没有\xe2\x80\x99t看到错误。这些原子类型会被多个进程和线程以及 更改atomic_compare_exchange_strong_explicit(),因此它们每次都需要一个旧值,而 \xe2\x80\x99s 我总是这样做,oldValue = <Atomic_ type_variable>并且它总是工作正常。\n这只是偶然吗?我应该更喜欢使用atomic_load()吗?

\n

rvalue lvalue-to-rvalue c11 stdatomic

2
推荐指数
1
解决办法
2648
查看次数

为什么std :: enable_shared_from_this允许多个std :: shared_ptr实例?

有几个问题涵盖了的行为std::enable_shared_from_this,但我认为这不是重复的。

从继承的类std::enable_shared_from_this带有std::weak_ptr成员。当应用程序创建std::shared_ptr指向的子类的指向时std::enable_shared_from_thisstd::shared_ptr构造函数将检查std::weak_ptr,如果未初始化,则对其进行初始化并将std::weak_ptr控制块用于std::shared_ptr。但是,如果std::weak_ptr已初始化,则构造方法将std::shared_ptr使用新的控制块创建一个新对象。当两个std::shared_ptr实例之一的引用计数变为零并删除基础对象时,这会使应用程序崩溃。

struct C : std::enable_shared_from_this<C> {};

C *p = new C();
std::shared_ptr<C> p1(p);

// Okay, p1 and p2 both have ref count = 2
std::shared_ptr<C> p2 = p->shared_from_this();

// Bad: p3 has ref count 1, and C will be deleted twice
std::shared_ptr<C> p3(p);
Run Code Online (Sandbox Code Playgroud)

我的问题是:图书馆为什么会这样?如果std::shared_ptr构造函数知道对象是std::enable_shared_from_this子类并且费心检查std::weak_ptr字段,为什么它不总是对new使用相同的控制块std::shared_ptr,从而避免了潜在的崩溃?

因此,为什么在未初始化成员shared_from_this时方法失败 …

c++ shared-ptr weak-ptr c++17 enable-shared-from-this

2
推荐指数
1
解决办法
156
查看次数