我正面临一个我不知道如何解决的问题,希望社区可以提供帮助.
我正在编写一个管理"Lead"对象的应用程序.(这些是销售线索.)我的程序的一部分将从文本文件中导入潜在客户.现在,文本文件包含许多潜在的潜在客户,其中一些我想要导入,其中一些我不会.
为了便于编程(和使用),我将文本文件解析为List <Lead>对象,并使用DataGridView通过设置DataGridView的DataSource属性来显示潜在客户.
我想要做的是在网格中添加一个名为"导入"的列,其中包含一个复选框,用户可以选中该复选框以指示是否应导入每个导联.
我的第一个想法是从Lead派生一个班级:
public Class LeadWithImportCheckbox : Lead
{
bool bImport = false;
public bool Import { get { return bImport;} set { bImport = value;} } }
LeadWithImportCheckbox newLead = (LeadWithImportCheckbox)LeadFromParsingEngine;这是一个无效的演员表.
我看到的另一个选项是为LeadWithImportCheckbox创建一个构造函数:
public LeadWithImportCheckbox(Lead newlead) { base.Property1 = newlead.Property1; base.Property2 = newlead.Property2; .... base.Property_n = newlead.Property_n; }出于两个原因,这是有问题的.一,Lead对象有几十个属性,编写这个构造函数是PITA.
但更糟糕的是,如果我更改了Lead的底层结构,我需要记住返回并更改LeadWithImportCheckbox的构造函数.这对我的代码维护是一个危险.
有没有更好的方法来实现我的目标?
所以我有这个代码:
Node* SceneGraph::getFirstNodeWithGroupID(const int groupID)
{
return static_cast<Node*>(mTree->getNode(groupID));
}
Run Code Online (Sandbox Code Playgroud)
mTree-> getNode(groupID)返回PCSNode*.节点是从PCSNode公开派生的.
我在static_cast上找到的所有文档都说明了这一点:"static_cast运算符可用于操作,例如将指向基类的指针转换为指向派生类的指针."
然而,XCode(GCC)编译器表示static_cast从PCSNode*到Node*是无效的,不允许.
这是什么原因?当我将其切换为C风格的演员表时,编译器没有任何抱怨.
谢谢.
更新:即使问题得到解答,我也会发布编译器错误以确保完整性,以防其他人遇到同样的问题:
错误:语义问题:不允许从"PCSNode*"到"Node*"的Static_cast
我想对以下问题提出一些建议:假设你想为VCL控件编写适配器.所有适配器应具有相同的基类,但在包装特殊控件方面有所不同(例如,从TEdit获取值与从TSpinEdit获取值不同).所以第一个想法就是创建一个类层次结构
TAdapter = class
end;
TEditAdapter = class (TAdapter)
end;
TSpinEditAdapter = class (TAdapter)
end;
Run Code Online (Sandbox Code Playgroud)
现在我想引入一个字段来保存对vcl控件的引用.在我的特殊适配器中,我想 - 当然 - 使用具体的子类.但是Base类还应该包含一个引用(例如,如果我想使用适配器使控件可见).
可能性1(物业存取中的向下):
TAdapter = class
protected
FCtrl : TControl;
end;
TEditAdapter = class (TAdapter)
public
property Control : TEdit read GetControl write Setcontrol;
end;
{...}
function TEditAdapter.GetControl : TEdit;
begin
Result := FCtrl as TEdit;
end;
Run Code Online (Sandbox Code Playgroud)
因此,如果我实现一个特定的方法,我使用属性Control,如果我在基类中执行某些操作,则使用protected字段.
可能性2(使用通用基类):
TAdapter = class
end;
TAdapter <T : TControl> = class (TAdapter)
protected
FCtrl : T;
end;
TEditAdapter = class (TAdapter <TEdit>)
end;
Run Code Online (Sandbox Code Playgroud)
您更喜欢哪种解决方案?还是有第三种解决方案,哪种更好? …
我正在编写一个大型应用程序,我试图尽可能多地保存内存并提高性能.因此,当我有一个我知道的字段只有0 - 10或-100 - 100的值时,我尝试使用short
数据类型而不是int
.
但是,对于其余的代码来说,这意味着,当我调用这些函数时,我必须将简单的int
s 转发为short
s.例如:
方法签名
public void coordinates(short x, short y) ...
Run Code Online (Sandbox Code Playgroud)
方法调用
obj.coordinates((short) 1, (short) 2);
Run Code Online (Sandbox Code Playgroud)
这就像我的整个代码中的所有代码一样,因为文字被视为int
s并且不会根据函数参数自动向下转换或键入.
因此,一旦这种向下转发发生,任何性能或内存增益是否真的显着?或者转换过程如此高效,以至于我仍能获得一些收益?
我想弄清楚为什么我需要向下转换.我从拼贴中重读了我的笔记并找到了下面的例子.
class Student {...}
class Graduate exteds Student {
getResearchTopic(){...} // this method only exists in Graduate class.
}
Run Code Online (Sandbox Code Playgroud)
我们有一个ref类到Student类,想要访问getResearchTopic方法;
Student s1 = new Graduate();
if(s1 instanceof Graduate){
((Graduate)s1).getResearchTopic();
}
Run Code Online (Sandbox Code Playgroud)
向下倾斜的好例子哈?我的问题是为什么不首先宣布s1为毕业生?是否有一个真实的例子,我将不得不转发而不是使用实际类的实例?
pub struct WidgetWrap {
// ...
widget: RefCell<Box<Any>>,
}
Run Code Online (Sandbox Code Playgroud)
在某些时候,我想投Box<Any>
给Box<WidgetTrait>
let mut cell = widget.borrow_mut();
let w = cell.downcast_mut::<Box<WidgetTrait>>();
Run Code Online (Sandbox Code Playgroud)
这给了我这样的错误:
error: instantiating a type parameter with an incompatible type
`Box<WidgetTrait>`, which does not fulfill `'static` [E0144]
Run Code Online (Sandbox Code Playgroud)
这究竟意味着什么?
我看过如何解决:值可能包含引用; 添加`'static`绑定到`T`并尝试添加+ 'static
到处.
pub struct WidgetWrap {
// ...
widget: RefCell<Box<Any + 'static>>,
}
let mut cell = widget.borrow_mut();
let w = cell.downcast_mut::<Box<WidgetTrait + 'static>>();
Run Code Online (Sandbox Code Playgroud)
它修复了编译错误,但是当我尝试打开如下所示的downcasrap框时失败.是的,盒子的内容是一个实现的对象WidgetTrait
.
显然,我在Rust中的编码水平我不太了解,但也许有人可以帮助我更好地掌握上述任务中涉及的概念.
我想在不更改现有类的情况下添加额外的功能。
说,
class base{
public:
int i;
base(){i = 1;}
virtual void do_work(){ /*Do some work*/ }
};
Run Code Online (Sandbox Code Playgroud)
如果我想serialization
向其中添加成员函数,我只需创建一个派生类
class derived : public base{
public:
void serialize();
};
void derived::serialize(){
cout << "derived class" << endl;
}
Run Code Online (Sandbox Code Playgroud)
我确实需要处理现有的base
对象,例如
int main(){
base a;
derived & b = static_cast<derived &>(a);
b.serialize();
}
Run Code Online (Sandbox Code Playgroud)
这个例子运行没有问题。但我确实知道一般情况下应该避免这种downcast
情况static_cast
。
但我想知道对于downcast
这一特定用例是否可以被认为是安全的,因为该类derived
只有一个额外的成员函数。它是否会有一些潜在的未定义的访问行为vtable
?
我正在将一些Python移植到Rust作为学习练习,需要从文件或标准输入中获取输入.我保留了一个结构中输入的句柄,所以我想我只是做了一个Box<io::Read>
但是我遇到了一个需要寻求输入的情况,而seek
不是Read
特征的一部分.我知道你不能在管道中寻找,所以我要继续并且现在假设这个方法只在输入是一个文件时才被调用,但我的问题是我无法在Rust中检查它和downcast.
我知道我可以使用enum作为两种输入类型,但似乎应该有一种更优雅的方式来做到这一点.这就是我的问题,你是如何做到这一点而不是弄得一团糟?
是否可以将stdin或文件包装在同一种缓冲区中,以便我可以使用该类型而不用担心IO的类型?
我有以下代码:
use std::thread;
use std::panic;
pub fn main(){
thread::spawn(move || {
panic::catch_unwind(|| {
// panic!("Oh no! A horrible error.");
let s: Option<u32> = None;
s.expect("Nothing was there!");
})
})
.join()
.and_then(|result| {
match result {
Ok(ref val) => {
println!("No problems. Result was: {:?}", val);
}
Err(ref err) => {
if let Some(err) = err.downcast_ref::<&'static str>() {
println!("Error: {}", err);
} else {
println!("Unknown error type: {:?}", err);
}
}
}
result
});
}
Run Code Online (Sandbox Code Playgroud)
当我panic!
直接触发 a 时(通过取消注释上面代码中的行),然后我得到一个包含我的错误消息的输出:
use …
Run Code Online (Sandbox Code Playgroud) 我无法将List of Fruit转换为List中包含的Fruit子类.
public class Response {
private List<Fruit> mFruitList;
public List<Fruit> getFruitList() {
return mFruitList;
}
}
public class Fruit {
}
public class Orange extends Fruit {
}
List<Fruit> oranges = response.getFruitList();
Run Code Online (Sandbox Code Playgroud)
如何投射橙子以使其成为橙类列表?这是一个糟糕的设计模式吗?基本上我从服务器获取JSON响应是一个水果列表.对于Web服务的每个特定调用,我知道Fruit将获得什么子类,因此我需要适当地转换该List.