我有一个定义如下的car_table数组:
struct car_traits_type;
enum { U = 0, A = 1, M = 2 };
struct car_type {
const char * name;
int type;
car_traits_type * traits;
};
struct car_traits_type {
const char * color;
};
struct automatic_traits_type : car_traits_type {
automatic_traits_type(const char * color) : car_traits_type{color}, top_speed{55} {}
automatic_traits_type(const char * color, int _top_speed) : car_traits_type{color}, top_speed{_top_speed} {}
int top_speed;
};
struct car_type car_table[MAX_CARS] = {
{"Honda", A, new automatic_traits_type{"blue"} },
{"Porsche", U, new car_traits_type{"green"} },
{"Toyota", A, new automatic_traits_type{"blue", 65} },
{ nullptr, 0, nullptr }
};
在驱动程序代码中,我键入将特征指针投射到派生类:
car = car_lookup("Porsche");
printf("%s is painted %s\n",car_table[car].name, car_table[car].traits->color);
int car2 = car_lookup("Toyota");
printf("%s has a top speed of %d\n",car_table[car2].name, static_cast<automatic_traits_type *>(car_table[car2].traits)->top_speed);
这正常工作并执行。
我想创建一个实用函数或宏来执行类型转换,以使我的驱动程序代码不再那么冗长。我尝试使用枚举来捕获类型,以便可以在驱动程序代码中完成适当的类型转换,即:
#define CAR_TRAITS( type, car ) (( (type) == 1) ? \
static_cast<automatic_traits_type *>(car_table[(car)].traits) : \
static_cast<car_traits_type *>(car_table[(car)].traits))
int car3 = car_lookup("Honda");
int type = car_table[car3].type;
printf("%d type", type);
printf("%s has a top speed of %d\n",car_table[car3].name, CAR_TRAITS(type,car3)->top_speed);
但是,出现以下编译错误:
module2.cpp:30:86: error: ‘struct car_traits_type’ has no member named ‘top_speed’
printf("%s has a top speed of %d\n",car_table[car3].name, CAR_TRAITS(type,car3)->top_speed);
我希望对CAR_TRAITS
宏的求值类型将表达式强制转换为automatic_traits_type *
。
答案 0 :(得分:2)
三元表达式将具有一个返回类型。我猜想automatic_traits_type*
会自动转换为car_traits_type*
以容纳this
更好的方法是将继承用作接口。例如。拥有get_color
虚拟功能,而不是访问实现细节。
答案 1 :(得分:0)
您的原型有很多需要改进的地方。即
std::unique_ptr
和enum class
。std::array
)与传统的枚举相比具有多个优点。dynamic_cast
代替传统数组也有一些优点。#include <iostream>
#include <memory>
struct car_traits_type;
enum class CarType { U = 0, A = 1, M = 2 };
struct car_type {
car_type(std::string name_, std::unique_ptr<car_traits_type> traits_)
: name(std::move(name_)), traits(std::move(traits_))
{}
std::string name;
std::unique_ptr<car_traits_type> traits;
};
struct car_traits_type {
car_traits_type() = default;
explicit car_traits_type(std::string color)
: color(std::move(color))
{}
virtual ~car_traits_type() = default;
virtual CarType type() const { return CarType::U; }
std::string color;
};
struct automatic_traits_type : car_traits_type {
automatic_traits_type() = default;
explicit automatic_traits_type(std::string color, int _top_speed = 55)
: car_traits_type(std::move(color)), top_speed(_top_speed)
{}
CarType type() const override { return CarType::A; }
int top_speed;
};
std::array<car_type, 3> cars = {
car_type{"Honda", std::make_unique<automatic_traits_type>("blue")},
car_type{"Porsche", std::make_unique<car_traits_type >("green")},
car_type{"Toyota", std::make_unique<automatic_traits_type>("blue", 65)}
};
int main() {
for (auto& ct : cars)
{
std::cout << ct.name;
if (ct.traits)
{
std::cout << ' ' << static_cast<int>(ct.traits->type()) << ' ' << ct.traits->color;
if (auto* at = dynamic_cast<automatic_traits_type*>(ct.traits.get()))
std::cout << ' ' << at->top_speed;
}
std::cout << '\n';
}
return 0;
}
... 总结:使用现代内存管理和虚拟类层次结构,可以解决您的问题。
请看下面的代码作为工作示例(它需要C ++ 14,希望您的编译器支持它)
import schedule
import time
import datetime
import uuid
from flask import Flask, request
from multiprocessing import Process
app = Flask(__name__)
t = None
job_timer = None
def run_job(id):
""" sample job with parameter """
global job_timer
print("timer job id={}".format(id))
print("timer: {:.4f}sec".format(time.time() - job_timer))
job_timer = time.time()
def run_schedule():
""" infinite loop for schedule """
global job_timer
job_timer = time.time()
while 1:
schedule.run_pending()
time.sleep(1)
@app.route('/timer/<string:status>')
def mytimer(status, nsec=10):
global t, job_timer
if status=='on' and not t:
schedule.every(nsec).seconds.do(run_job, str(uuid.uuid4()))
t = Process(target=run_schedule)
t.start()
return "timer on with interval:{}sec\n".format(nsec)
elif status=='off' and t:
if t:
t.terminate()
t = None
schedule.clear()
return "timer off\n"
return "timer status not changed\n"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
答案 2 :(得分:0)
我不确定100%是否理解您的动机,所以让我假设您想对已定义的类型进行尽可能小的更改,仅在调用者站点上修复强制转换。此外,这里:
int car2 = car_lookup("Toyota");
printf("%s has a top speed of %d\n",car_table[car2].name, static_cast<automatic_traits_type *>(car_table[car2].traits)->top_speed);
呼叫者需要知道"Toyota"
有一个top_speed
,否则它们会在运行时出现问题。假设呼叫者知道他们得到的汽车有top_speed
。在那种情况下,我可能会使用
int get_top_speed(const car& c) {
return static_cast<automatic_traits_type *>(c.traits)->top_speed;
}