我现在对继承感到非常困惑。我打算简单地覆盖变量的初始值。在下面的代码中,我只是继承了基类并尝试获取它的名称,该名称保存为带有该类的字符串。我期望派生类可以覆盖此值,但它不会这样做。
我的预期出局是
val phDf = sqlContext.phoenixTableAsDataFrame("TABLE1", Array("ID", "NAME"), conf = hbaseConf)
但是我得到了
Derived
Derived
实施以下内容的正确方法是什么?
Base
Base
答案 0 :(得分:3)
实施以下内容的正确方法是什么?
听起来没有意义,这实际上取决于你想要达到的目标。
我要猜测我们只是在询问一个对象是什么类型,无论我们调用哪个接口:
struct Base {
virtual ~Base() = default;
virtual const std::string id() const {
return "Base";
}
};
struct Derived : Base {
virtual const std::string id() const override {
return "Derived";
}
};
这是另一种方式:
struct Base {
virtual Base(std::string ident = "Base")
: _id(std::move(ident))
{}
virtual ~Base() = default;
std::string& id() const {
return _id;
}
private:
std::string _id;
};
struct Derived : Base {
Derived() : Base("Derived") {}
};
另外,使用值是接口,但请注意,这将禁用赋值运算符
struct Base {
virtual Base(std::string ident = "Base")
: id(std::move(ident))
{}
virtual ~Base() = default;
const std::string id;
};
struct Derived : Base {
Derived() : Base("Derived") {}
};
此列表并非详尽无遗。
答案 1 :(得分:2)
存在虚函数,而非虚拟成员变量。
您在Derived
课程中所做的是定义一个隐藏它的父级的新成员变量id_
。但是,id()
函数指的是该上下文中id_
定义的 。
如果要覆盖行为,则应覆盖id()
函数:
class Derived: public Base {
std::string id() const override { return "Derived"; }
};
答案 2 :(得分:1)
为什么不简单地给Base
一个构造函数设置id
并让Derived
调用此构造函数及其被覆盖的'值?繁荣:'虚拟数据'根据派生类型。
话虽如此,虚拟方法可能更类似于封装,并为以后更精细的行为提供机会。
(编辑:我将此作为评论发布,然后将其转换,此时理查德刚刚击败我发布答案。没有复制!)
答案 3 :(得分:0)
由于函数id()是虚拟的,因此在两种情况下,对象指针都只是派生类型。
Base* b = new Derived(); // object type is Derived
b->id();
这里b是Derived类型的指针 但是" Derived" class没有id()的实现,因为在虚拟查找表中没有id()的条目用于派生类对象,因此它将调用基类函数id()
同样其他情况
Derived* d = new Derived(); //object type is Derived
d->id();
因为在派生类中没有定义id()方法,所以它只会调用基类id()。
另一个疑问是你如何初始化变量" id _"在班里?