这是在Java中使用多接口继承的示例,这是一个问题.
请注意,我完全知道为什么会出现问题,这不是我的问题.问题是关于如何命名这个特定的多接口继承歧义,如果它有一个名称.
例如,在C++中,当您使用多个实现继承并且无法确定使用哪个重写方法时出现的歧义称为"钻石问题":
http://en.wikipedia.org/wiki/Diamond_problem
再一次,我知道这不是同一个问题:那不是重点.关键是在之前的案例中创造了一个名称.
而且我想知道我将要描述的问题是否存在名称.
下面是另一种多重继承的示例,其中一个接口继承自另外两个具有不兼容方法返回类型的接口:
interface A {
void a();
Integer c();
}
interface B {
void b();
Long c();
}
interface MI extends A, B {...}
Run Code Online (Sandbox Code Playgroud)
(使用'extends'关键字注意工作中的多个接口继承)
你做不到,因为:
A型和B型不兼容; 两者都定义c()但具有不相关的返回类型
有没有一个名字来描述这种情况?
我正在做一个我没有开始的大项目.我的任务是为已有的功能添加一些额外的功能.我处于一种必须使用虚拟继承的情况,因为我有一个钻石模型.情况如下图所示:
Base class
/ \
/ \
My new class A class that was there before (OldClass)
\ /
\ /
\ /
\ /
My other new class
Run Code Online (Sandbox Code Playgroud)
为了实现这一点,中间的两个类都必须从基础继承,public virtual而不是仅仅public.所以:
class OldClass: public BaseClass {}
Run Code Online (Sandbox Code Playgroud)
必须成为:
class OldClass: public virtual BaseClass {}
Run Code Online (Sandbox Code Playgroud)
由于这个项目非常庞大,我正在研究它的一小部分,我不想通过这样做来打破它.我的adhoc测试工作,程序似乎工作正常,但我仍然怀疑.
所以我的问题是:通过添加virtual关键字,我应该期待哪些副作用和后果?有什么值得担心的吗?
我试图找出一个有趣的多继承问题.
祖父母是一个有多种方法的接口类:
class A
{
public:
virtual int foo() = 0;
virtual int bar() = 0;
};
Run Code Online (Sandbox Code Playgroud)
然后有部分完成此接口的抽象类.
class B : public A
{
public:
int foo() { return 0;}
};
class C : public A
{
public:
int bar() { return 1;}
};
Run Code Online (Sandbox Code Playgroud)
我想要使用的类继承自两个父类,并指定通过using指令应该来自哪个方法:
class D : public B, public C
{
public:
using B::foo;
using C::bar;
};
Run Code Online (Sandbox Code Playgroud)
当我尝试实例化DI获取错误以尝试实例化抽象类时.
int main()
{
D d; //<-- Error cannot instantiate abstract class.
int test = d.foo();
int test2 = d.bar();
return …Run Code Online (Sandbox Code Playgroud) 我有以下代码:
#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
#define MNAME 30
class Person {
public:
char name[MNAME + 1];
};
class Student : public Person {
};
class Staff : public Person {
};
class Faculty : public Student, public Staff {
};
int _tmain(int argc, _TCHAR* argv[])
{
Faculty faculty;
cout << "Address of faculty.Person::name: " << &faculty.Person::name << endl;
cout << "Address of faculty.Student::name: " << &faculty.Student::name << endl;
cout << "Address of faculty.Staff::name: " << …Run Code Online (Sandbox Code Playgroud) 守则如下:
#include <iostream>
using namespace std;
class Animal{
int a;
public:
Animal(int a) : a(a){}
int geta(){return a;}
};
class Bird : virtual public Animal{
string b;
public:
Bird(int a , string b) : Animal(a) , b(b){}
};
class Fish : virtual public Animal{
int f;
public:
Fish(int a , int f) : Animal(a) , f(f){}
};
class Unknown : public Bird, public Fish{
char u;
public:
Unknown(int a , int f , string b , char u …Run Code Online (Sandbox Code Playgroud) 我发现这个程序的编译器之间存在一些不一致,
struct A {
};
struct B : public A {
float m;
};
struct C : public A {
B b;
float n;
};
struct D : public A {
float n;
B b;
};
static_assert(sizeof(A) == 1, "");
static_assert(sizeof(B) == 4, "");
static_assert(sizeof(C) == 8, ""); // most compilers say this is 12
static_assert(sizeof(D) == 8, "");
Run Code Online (Sandbox Code Playgroud)
大多数编译器断言sizeof(C)== 8说sizeof(C)实际上是12.我发现的唯一编译器没有,并说它是8是Microsoft Visual Studio 2010.
我被告知的原因是,比我更聪明的人,是B中有两个单独的A参考,需要保留彼此不同的个体偏移.首先,从C导出的A在偏移0处,并且第二个A内部成员b不能与第一个A在0处的偏移量相同,因此插入了4个字节的填充.
由于大多数编译器已经实现了这种行为,我想知道你需要什么案例来确保两个A都有不同的引用?寻找一些关于为什么会这样的直觉?
有人说这可能是标准要求的条件,我们很好奇它的原因是什么?
谢谢
Java不允许多重继承来保护钻石问题.它使用接口来处理这个问题.
然后就是使用界面的情况吧
interface A{
run();
}
interface B{
run();
}
class C implements A, B{
run() {} //Which interface we are using?
}
Run Code Online (Sandbox Code Playgroud)
当我们run()在类中调用该方法时,我们C如何确定我们使用的是哪个接口?
我有很难去骗取下班的大小是什么?
我正在使用MSVS 2008(VC 9.0编译器).我已经读过,如果我没有声明虚函数(在下面的例子中),那么D类将包含2个额外的指针(来自B的1和来自C的另一个),它将指向A的共享实例.
但是在下面的情况下,每个类的内存映射是什么(也有虚函数)?
class A
{
public:
int a;
virtual void Func();
public:
A(void);
~A(void);
};
class B :virtual public A
{
public:
int b;
virtual void Func();
public:
B(void);
~B(void);
};
class C: virtual public A
{
public:
int c;
virtual void Func();
public:
C(void);
~C(void);
};
class D : public B, public C
{
public:
int d;
virtual void Func();
public:
D(void);
~D(void);
};
int _tmain(int argc, _TCHAR* argv[])
{
cout << "size of Class A …Run Code Online (Sandbox Code Playgroud) c++ virtual-functions virtual-inheritance vtable diamond-problem
请考虑以下代码:
// Preamble
#include <iostream>
#include <type_traits>
// A base class
template <class T>
struct base {void operator()(T){};};
// Two derived classes inheriting from the same base classes
template <class... T>
struct derived1: base<T>... {using base<T>::operator()...;};
template <class... T>
struct derived2: base<T>... {using base<T>::operator()...;};
// A class inheriting from both derived1 and derived2
template <class T0, class... T>
struct functor: derived1<T0>, derived2<T0, T...> {
using derived1<T0>::operator();
using derived2<T0, T...>::operator();
};
// Main function
int main() {
std::cout << std::is_invocable_v<functor<int, float, …Run Code Online (Sandbox Code Playgroud) 我尝试实现一些接口及其子接口。这是我的想法:
Interface
/ \
Interface2 InterfaceDefination
| /
Interface2Defination
Run Code Online (Sandbox Code Playgroud)
这是我的代码:
Interface
/ \
Interface2 InterfaceDefination
| /
Interface2Defination
Run Code Online (Sandbox Code Playgroud)
我的预期输出是:
method1 from InterfaceDefination
method2 from Interface2Defination
print from Interface2Defination
Run Code Online (Sandbox Code Playgroud)
但意外地我收到了这些错误:
main.cpp:33:24: error: variable type 'Interface2Defination' is an abstract class
Interface2Defination c;
^
main.cpp:5:16: note: unimplemented pure virtual method 'method1' in 'Interface2Defination'
virtual void method1() = 0;
^
1 error generated.
make: *** [<builtin>: main.o] Error 1
exit status 2
Run Code Online (Sandbox Code Playgroud)
https://godbolt.org/z/9ncoGfn4P
在这种情况下,错误意味着using关键字没有使方法method1在 class 中可用Interface2Defination。我应该用它做什么?
diamond-problem ×10
c++ ×8
inheritance ×4
class ×2
java ×2
abstract ×1
ambiguous ×1
c++17 ×1
compiler-bug ×1
constructor ×1
interface ×1
sizeof ×1
vtable ×1