我有以下层次结构:
class base
{
public:
virtual ~base(){}
virtual void foo() {}
};
template <typename T>
class derived1 : public base
{
virtual void foo() {};
};
template <typename T>
class derived2 : public base
{
virtual void foo() {};
};
Run Code Online (Sandbox Code Playgroud)
现在给出一个指向base的指针,我想知道底层是derived1还是derived2.问题是derived1和derived2都可以专门用于许多不同类型,使用dynamic_cast来测试向下转换需要知道模板类型.我最终得到了凌乱,不稳定和不完整的代码:
base* b = new derived1<int>();
if (dynamic_cast<derived1<int>*> ||
dynamic_cast<derived1<unsigned int>*> ||
dynamic_cast<derived1<double>*>)
std::cout << "is derived1";
else if (dynamic_cast<derived2<int>*> ||
dynamic_cast<derived2<unsigned int>*> ||
dynamic_cast<derived2<double>*>)
std::cout << "is derived2";
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法,可以处理任何类型的专业化?
我有一个状态模式的实现,其中每个状态处理从事件队列获取的事件.State
因此,基类具有纯虚方法void handleEvent(const Event*)
.事件继承基Event
类,但每个事件都包含可以是不同类型的数据(例如int,string ......或者其他).handleEvent
必须确定接收事件的运行时类型,然后执行向下转换以提取事件数据.事件是动态创建并存储在队列中的(因此在此处进行向上转换 ......).
我知道向下倾斜是一种糟糕设计的标志,但在这种情况下可以避免它吗?我正在考虑访问者模式,其中基类State将包含每个事件的虚拟处理程序,但是然后需要在代码片段中进行向下转换,该代码将队列中的事件从队列中取出并将其传递到当前状态.(至少在这种情况下,大switch(eventID)
只会在一个地方......).访客模式是避免向下转换的最佳方式(最佳实践)吗?
这是伪代码(我boost::shared_ptr
在这个例子中传递,但无论如何都会发生向下转换):
enum EventID
{
EVENT_1,
EVENT_2,
...
};
class Event
{
EventID id;
public:
Event(EventID id):id(id){}
EventID id() const {return id;}
virtual ~Event() = 0;
};
class Event1 : public Event
{
int n;
public:
Event1(int n):Event(EVENT_1), n(n){}
int getN() const {return n;}
};
class Event2 : public Event
{
std::string s; …
Run Code Online (Sandbox Code Playgroud) 我有两个类 - 一个继承自另一个.我想知道如何转换(或创建一个新的变量)子类.我已经搜索了一下,大部分都是"向下倾斜",这似乎是不受欢迎的,并且有一些稍微狡猾的解决方法,比如设置实例.上课 - 虽然这似乎不是一个好方法.
例如. http://www.gossamer-threads.com/lists/python/python/871571 http://code.activestate.com/lists/python-list/311043/
子问题 - 真的那么糟糕吗?如果是这样的话?
我在下面简化了代码示例 - 基本上我有一些代码在对x,y数据进行一些分析后创建了一个Peak对象.在这段代码之外我知道数据是'PSD'数据功率谱密度 - 所以它有一些额外的属性.我如何从山顶投降到Psd_Peak?
"""
Two classes
"""
import numpy as np
class Peak(object) :
"""
Object for holding information about a peak
"""
def __init__(self,
index,
xlowerbound = None,
xupperbound = None,
xvalue= None,
yvalue= None
):
self.index = index # peak index is index of x and y value in psd_array
self.xlowerbound = xlowerbound
self.xupperbound = xupperbound
self.xvalue = xvalue
self.yvalue = yvalue
class Psd_Peak(Peak) …
Run Code Online (Sandbox Code Playgroud) 我觉得这是不可能的,但如果没有,那将是非常有用的.
我试图以子类只有新方法,没有新构造函数,没有新字段的方式扩展父类.因此子类的基础数据结构与父类相同.当我想为内置的java类(例如Vector3d
)提供附加函数时,这往往会发生.鉴于底层数据是相同的,可以以任何方式将初始化为父类的对象向下转换为子类,以便我可以使用添加的功能.作为我的意思的一个例子,见下文
import javax.vecmath.Vector3d;
public class Vector3dPlus extends Vector3d{
//same fields, same constructors as Vector3d
public double extraMethod(){
return x+y+z;
}
}
Run Code Online (Sandbox Code Playgroud)
尝试使用添加到Vector3d的新方法
import javax.vecmath.Vector3d;
public class Test {
public static void main(String[] args) {
Vector3d basic=new Vector3d(1,2,3);
useExtraMethod(basic); //this line correctly raises an exception, but is there a way around that
}
public static void useExtraMethod(Vector3dPlus plus){
System.out.println(plus.extraMethod());
}
}
Run Code Online (Sandbox Code Playgroud)
很明显,java对此感到不安,因为通常我们无法保证Vector3dPlus
方法适用于所有方法Vector3d
.不过反正是有,我可以对Java的基础数据结构是相同的,因此允许所有所有的向下转换说Vector3d
来 Vector3dPlus
.
我处理这个问题的当前方法是将所有额外的方法放在一个通用的实用程序类中,但这显然有点可怕
在给父母提供数据的情况下,创建孩子的最佳方法是哪种?是否可以在子类上使用包含所有父值的方法:
public class Child extends Person {
public Child(Parent p) {
this.setParentField1(p.getParentField1());
this.setParentField2(p.getParentField2());
this.setParentField3(p.getParentField3());
// other parent fields.
}
}
Run Code Online (Sandbox Code Playgroud)
复制父数据ti子对象?
Child child = new Child(p);
Run Code Online (Sandbox Code Playgroud) 让我们说,Class B
扩展class A
并class A
克隆如下:
public class A implements Cloneable {
public Object clone() throws CloneNotSupportedException {
A ac = (A) super.clone();
return ac;
}
}
public class B extends A {
public Object clone() throws CloneNotSupportedException {
B a = (B) super.clone();
return a;
}
}
Run Code Online (Sandbox Code Playgroud)
为什么在下一行中从A到B进行向下转换是合法的:
B a = (B) super.clone(); // (super of B is A)
Run Code Online (Sandbox Code Playgroud)
而下一个下线是运行时错误?
A a = new A();
B b = (B) a.clone();
Run Code Online (Sandbox Code Playgroud)
提前致谢!
当java可以隐式地进行转换时,为什么不隐式地进行转换?请用一些简单的例子来解释一下?
假设我们有以下玩具界面:
interface Speakable
{
public abstract void Speak();
}
interface Flyer
{
public abstract void Fly();
}
Run Code Online (Sandbox Code Playgroud)
我们有一个实现两个接口的类:
class Duck implements Speakable, Flyer
{
public void Speak()
{
System.out.println("quack quack don't eat me I taste bad.");
}
public void Fly()
{
System.out.println("I am flying");
}
}
Run Code Online (Sandbox Code Playgroud)
在这一点上,我看到了不同的方法来调用方法Duck
,我无法决定哪一个是最佳实践.考虑这种情况:
public class Lab
{
private static void DangerousSpeakAndFly(Object x)
{
Speakable temp = (Speakable) x;
temp.Speak();
Flyer temp2= (Flyer) x;
temp2.Fly();
}
public static void main(String[] args)
{
Duck daffy= new …
Run Code Online (Sandbox Code Playgroud) 有人问这个关于字符串附加的问题.它string s; s = s + 2;
没有编译.人们给出了答案,说明operator+
被定义为模板函数而operator+=
不是,因此不应用自动向下转换(int(2)
to char(2)
).
原型是
template<typename _CharT, typename _Traits, typename _Alloc>
class basic_string{
basic_string&
operator+=(_CharT __c);
};
template<typename _CharT, typename _Traits, typename _Alloc>
inline basic_string<_CharT, _Traits, _Alloc>
operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs);
Run Code Online (Sandbox Code Playgroud)
为什么编译器不能只使用这个原型并将int(2)转换为char(2)?
basic_string<char, _T, _A> operator+(const basic_string<char, _T, _A>, char);
Run Code Online (Sandbox Code Playgroud)
编译器(G ++ 6.3.0)抱怨说
[Note] deduced conflicting types for parameter '_CharT' ('char' and 'int')
Run Code Online (Sandbox Code Playgroud) 我知道向下转换基本上是将父类指针或引用转换为派生类引用或指针,为此您使用dynamic_cast运算符。但我几乎想不出任何例子。你们能解释一下吗?
downcast ×10
inheritance ×5
java ×5
c++ ×4
casting ×3
oop ×2
clone ×1
dynamic-cast ×1
polymorphism ×1
python ×1
state ×1
upcasting ×1